From 5c592afebe53888d9687462af96851fba2be739e Mon Sep 17 00:00:00 2001 From: hailaz <739476267@qq.com> Date: Sat, 15 Jun 2019 17:51:48 +0800 Subject: [PATCH] Improve gtree unit testing. --- g/container/gtree/gtree_z_avl_tree_test.go | 193 +++++++++++++++--- g/container/gtree/gtree_z_b_tree_test.go | 147 +++++++++++-- .../gtree/gtree_z_redblack_tree_test.go | 193 ++++++++++++++++-- 3 files changed, 466 insertions(+), 67 deletions(-) diff --git a/g/container/gtree/gtree_z_avl_tree_test.go b/g/container/gtree/gtree_z_avl_tree_test.go index f20ed2601..8cf58032f 100644 --- a/g/container/gtree/gtree_z_avl_tree_test.go +++ b/g/container/gtree/gtree_z_avl_tree_test.go @@ -7,13 +7,15 @@ package gtree_test import ( + "fmt" + "testing" + "github.com/gogf/gf/g/container/gtree" + "github.com/gogf/gf/g/container/gvar" "github.com/gogf/gf/g/test/gtest" "github.com/gogf/gf/g/util/gutil" - "testing" ) - func Test_AVLTree_Basic(t *testing.T) { gtest.Case(t, func() { m := gtree.NewAVLTree(gutil.ComparatorString) @@ -24,6 +26,7 @@ func Test_AVLTree_Basic(t *testing.T) { gtest.Assert(m.Size(), 1) gtest.Assert(m.IsEmpty(), false) + gtest.Assert(m.GetOrSet("key2", "val2"), "val2") gtest.Assert(m.GetOrSet("key2", "val2"), "val2") gtest.Assert(m.SetIfNotExist("key2", "val2"), false) @@ -37,9 +40,14 @@ func Test_AVLTree_Basic(t *testing.T) { gtest.AssertIN("val3", m.Values()) gtest.AssertIN("val1", m.Values()) + m.Sets(map[interface{}]interface{}{"key3": "val3", "key1": "val1"}) + m.Flip() gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"}) + m.Flip(gutil.ComparatorString) + gtest.Assert(m.Map(), map[interface{}]interface{}{"key3": "val3", "key1": "val1"}) + m.Clear() gtest.Assert(m.Size(), 0) gtest.Assert(m.IsEmpty(), true) @@ -49,14 +57,45 @@ func Test_AVLTree_Basic(t *testing.T) { }) } func Test_AVLTree_Set_Fun(t *testing.T) { - m := gtree.NewAVLTree(gutil.ComparatorString) - m.GetOrSetFunc("fun", getValue) - m.GetOrSetFuncLock("funlock", getValue) - gtest.Assert(m.Get("funlock"), 3) - gtest.Assert(m.Get("fun"), 3) - m.GetOrSetFunc("fun", getValue) - gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false) - gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false) + //GetOrSetFunc lock or unlock + gtest.Case(t, func() { + m := gtree.NewAVLTree(gutil.ComparatorString) + gtest.Assert(m.GetOrSetFunc("fun", getValue), 3) + gtest.Assert(m.GetOrSetFunc("fun", getValue), 3) + gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3) + gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3) + gtest.Assert(m.Get("funlock"), 3) + gtest.Assert(m.Get("fun"), 3) + }) + //SetIfNotExistFunc lock or unlock + gtest.Case(t, func() { + m := gtree.NewAVLTree(gutil.ComparatorString) + gtest.Assert(m.SetIfNotExistFunc("fun", getValue), true) + gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false) + gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), true) + gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false) + gtest.Assert(m.Get("funlock"), 3) + gtest.Assert(m.Get("fun"), 3) + }) + +} + +func Test_AVLTree_Get_Set_Var(t *testing.T) { + gtest.Case(t, func() { + m := gtree.NewAVLTree(gutil.ComparatorString) + gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), true) + gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), false) + gtest.AssertEQ(m.GetVarOrSet("key1", "val1"), gvar.New("val1", true)) + gtest.AssertEQ(m.GetVar("key1"), gvar.New("val1", true)) + }) + + gtest.Case(t, func() { + m := gtree.NewAVLTree(gutil.ComparatorString) + gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true)) + gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true)) + gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true)) + gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true)) + }) } func Test_AVLTree_Batch(t *testing.T) { @@ -66,27 +105,61 @@ func Test_AVLTree_Batch(t *testing.T) { m.Removes([]interface{}{"key1", 1}) gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"}) } -func Test_AVLTree_Iterator(t *testing.T){ - expect := map[interface{}]interface{}{1: 1, "key1": "val1"} + +func Test_AVLTree_Iterator(t *testing.T) { + keys := []string{"1", "key1", "key2", "key3", "key4"} + keyLen := len(keys) + index := 0 + + expect := map[interface{}]interface{}{"key4": "val4", 1: 1, "key1": "val1", "key2": "val2", "key3": "val3"} m := gtree.NewAVLTreeFrom(gutil.ComparatorString, expect) m.Iterator(func(k interface{}, v interface{}) bool { + gtest.Assert(k, keys[index]) + index++ gtest.Assert(expect[k], v) return true }) - // 断言返回值对遍历控制 - i := 0 - j := 0 - m.Iterator(func(k interface{}, v interface{}) bool { - i++ + + m.IteratorDesc(func(k interface{}, v interface{}) bool { + index-- + gtest.Assert(k, keys[index]) + gtest.Assert(expect[k], v) return true }) - m.Iterator(func(k interface{}, v interface{}) bool { - j++ - return false + + m.Print() + // 断言返回值对遍历控制 + gtest.Case(t, func() { + i := 0 + j := 0 + m.Iterator(func(k interface{}, v interface{}) bool { + i++ + return true + }) + m.Iterator(func(k interface{}, v interface{}) bool { + j++ + return false + }) + gtest.Assert(i, keyLen) + gtest.Assert(j, 1) }) - gtest.Assert(i, 2) - gtest.Assert(j, 1) + + gtest.Case(t, func() { + i := 0 + j := 0 + m.IteratorDesc(func(k interface{}, v interface{}) bool { + i++ + return true + }) + m.IteratorDesc(func(k interface{}, v interface{}) bool { + j++ + return false + }) + gtest.Assert(i, keyLen) + gtest.Assert(j, 1) + }) + } func Test_AVLTree_Clone(t *testing.T) { @@ -100,4 +173,78 @@ func Test_AVLTree_Clone(t *testing.T) { m_clone.Remove("key1") //修改clone map,原 map 不影响 gtest.AssertIN("key1", m.Keys()) -} \ No newline at end of file +} + +func Test_AVLTree_LRNode(t *testing.T) { + expect := map[interface{}]interface{}{"key4": "val4", "key1": "val1", "key2": "val2", "key3": "val3"} + //safe + gtest.Case(t, func() { + m := gtree.NewAVLTreeFrom(gutil.ComparatorString, expect) + gtest.Assert(m.Left().Key, "key1") + gtest.Assert(m.Right().Key, "key4") + }) + //unsafe + gtest.Case(t, func() { + m := gtree.NewAVLTreeFrom(gutil.ComparatorString, expect, true) + gtest.Assert(m.Left().Key, "key1") + gtest.Assert(m.Right().Key, "key4") + }) +} + +func Test_AVLTree_CeilingFloor(t *testing.T) { + expect := map[interface{}]interface{}{ + 20: "val20", + 6: "val6", + 10: "val10", + 12: "val12", + 1: "val1", + 15: "val15", + 19: "val19", + 8: "val8", + 4: "val4"} + //found and eq + gtest.Case(t, func() { + m := gtree.NewAVLTreeFrom(gutil.ComparatorInt, expect) + c, cf := m.Ceiling(8) + gtest.Assert(cf, true) + gtest.Assert(c.Value, "val8") + f, ff := m.Floor(20) + gtest.Assert(ff, true) + gtest.Assert(f.Value, "val20") + }) + //found and neq + gtest.Case(t, func() { + m := gtree.NewAVLTreeFrom(gutil.ComparatorInt, expect) + c, cf := m.Ceiling(9) + gtest.Assert(cf, true) + gtest.Assert(c.Value, "val10") + f, ff := m.Floor(5) + gtest.Assert(ff, true) + gtest.Assert(f.Value, "val4") + }) + //nofound + gtest.Case(t, func() { + m := gtree.NewAVLTreeFrom(gutil.ComparatorInt, expect) + c, cf := m.Ceiling(21) + gtest.Assert(cf, false) + gtest.Assert(c, nil) + f, ff := m.Floor(-1) + gtest.Assert(ff, false) + gtest.Assert(f, nil) + }) +} + +func Test_AVLTree_Remove(t *testing.T) { + m := gtree.NewAVLTree(gutil.ComparatorInt) + for i := 1; i <= 50; i++ { + m.Set(i, fmt.Sprintf("val%d", i)) + } + expect := m.Map() + gtest.Case(t, func() { + for k, v := range expect { + m1 := m.Clone() + gtest.Assert(m1.Remove(k), v) + gtest.Assert(m1.Remove(k), nil) + } + }) +} diff --git a/g/container/gtree/gtree_z_b_tree_test.go b/g/container/gtree/gtree_z_b_tree_test.go index 1596bd175..8659b5366 100644 --- a/g/container/gtree/gtree_z_b_tree_test.go +++ b/g/container/gtree/gtree_z_b_tree_test.go @@ -7,16 +7,22 @@ package gtree_test import ( + "fmt" + "testing" + "github.com/gogf/gf/g/container/gtree" + "github.com/gogf/gf/g/container/gvar" "github.com/gogf/gf/g/test/gtest" "github.com/gogf/gf/g/util/gutil" - "testing" ) func Test_BTree_Basic(t *testing.T) { gtest.Case(t, func() { m := gtree.NewBTree(3, gutil.ComparatorString) m.Set("key1", "val1") + + gtest.Assert(m.Height(), 1) + gtest.Assert(m.Keys(), []interface{}{"key1"}) gtest.Assert(m.Get("key1"), "val1") @@ -44,15 +50,47 @@ func Test_BTree_Basic(t *testing.T) { gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) }) } + func Test_BTree_Set_Fun(t *testing.T) { - m := gtree.NewBTree(3, gutil.ComparatorString) - m.GetOrSetFunc("fun", getValue) - m.GetOrSetFuncLock("funlock", getValue) - gtest.Assert(m.Get("funlock"), 3) - gtest.Assert(m.Get("fun"), 3) - m.GetOrSetFunc("fun", getValue) - gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false) - gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false) + //GetOrSetFunc lock or unlock + gtest.Case(t, func() { + m := gtree.NewBTree(3, gutil.ComparatorString) + gtest.Assert(m.GetOrSetFunc("fun", getValue), 3) + gtest.Assert(m.GetOrSetFunc("fun", getValue), 3) + gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3) + gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3) + gtest.Assert(m.Get("funlock"), 3) + gtest.Assert(m.Get("fun"), 3) + }) + //SetIfNotExistFunc lock or unlock + gtest.Case(t, func() { + m := gtree.NewBTree(3, gutil.ComparatorString) + gtest.Assert(m.SetIfNotExistFunc("fun", getValue), true) + gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false) + gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), true) + gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false) + gtest.Assert(m.Get("funlock"), 3) + gtest.Assert(m.Get("fun"), 3) + }) + +} + +func Test_BTree_Get_Set_Var(t *testing.T) { + gtest.Case(t, func() { + m := gtree.NewBTree(3, gutil.ComparatorString) + gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), true) + gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), false) + gtest.AssertEQ(m.GetVarOrSet("key1", "val1"), gvar.New("val1", true)) + gtest.AssertEQ(m.GetVar("key1"), gvar.New("val1", true)) + }) + + gtest.Case(t, func() { + m := gtree.NewBTree(3, gutil.ComparatorString) + gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true)) + gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true)) + gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true)) + gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true)) + }) } func Test_BTree_Batch(t *testing.T) { @@ -62,27 +100,61 @@ func Test_BTree_Batch(t *testing.T) { m.Removes([]interface{}{"key1", 1}) gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"}) } -func Test_BTree_Iterator(t *testing.T){ - expect := map[interface{}]interface{}{1: 1, "key1": "val1"} + +func Test_BTree_Iterator(t *testing.T) { + keys := []string{"1", "key1", "key2", "key3", "key4"} + keyLen := len(keys) + index := 0 + + expect := map[interface{}]interface{}{"key4": "val4", 1: 1, "key1": "val1", "key2": "val2", "key3": "val3"} m := gtree.NewBTreeFrom(3, gutil.ComparatorString, expect) m.Iterator(func(k interface{}, v interface{}) bool { + gtest.Assert(k, keys[index]) + index++ gtest.Assert(expect[k], v) return true }) - // 断言返回值对遍历控制 - i := 0 - j := 0 - m.Iterator(func(k interface{}, v interface{}) bool { - i++ + + m.IteratorDesc(func(k interface{}, v interface{}) bool { + index-- + gtest.Assert(k, keys[index]) + gtest.Assert(expect[k], v) return true }) - m.Iterator(func(k interface{}, v interface{}) bool { - j++ - return false + + m.Print() + // 断言返回值对遍历控制 + gtest.Case(t, func() { + i := 0 + j := 0 + m.Iterator(func(k interface{}, v interface{}) bool { + i++ + return true + }) + m.Iterator(func(k interface{}, v interface{}) bool { + j++ + return false + }) + gtest.Assert(i, keyLen) + gtest.Assert(j, 1) }) - gtest.Assert(i, 2) - gtest.Assert(j, 1) + + gtest.Case(t, func() { + i := 0 + j := 0 + m.IteratorDesc(func(k interface{}, v interface{}) bool { + i++ + return true + }) + m.IteratorDesc(func(k interface{}, v interface{}) bool { + j++ + return false + }) + gtest.Assert(i, keyLen) + gtest.Assert(j, 1) + }) + } func Test_BTree_Clone(t *testing.T) { @@ -96,4 +168,35 @@ func Test_BTree_Clone(t *testing.T) { m_clone.Remove("key1") //修改clone map,原 map 不影响 gtest.AssertIN("key1", m.Keys()) -} \ No newline at end of file +} + +func Test_BTree_LRNode(t *testing.T) { + expect := map[interface{}]interface{}{"key4": "val4", "key1": "val1", "key2": "val2", "key3": "val3"} + //safe + gtest.Case(t, func() { + m := gtree.NewBTreeFrom(3, gutil.ComparatorString, expect) + gtest.Assert(m.Left().Key, "key1") + gtest.Assert(m.Right().Key, "key4") + }) + //unsafe + gtest.Case(t, func() { + m := gtree.NewBTreeFrom(3, gutil.ComparatorString, expect, true) + gtest.Assert(m.Left().Key, "key1") + gtest.Assert(m.Right().Key, "key4") + }) +} + +func Test_BTree_Remove(t *testing.T) { + m := gtree.NewBTree(3, gutil.ComparatorInt) + for i := 1; i <= 100; i++ { + m.Set(i, fmt.Sprintf("val%d", i)) + } + expect := m.Map() + gtest.Case(t, func() { + for k, v := range expect { + m1 := m.Clone() + gtest.Assert(m1.Remove(k), v) + gtest.Assert(m1.Remove(k), nil) + } + }) +} diff --git a/g/container/gtree/gtree_z_redblack_tree_test.go b/g/container/gtree/gtree_z_redblack_tree_test.go index 6dbe85c6a..29406bad8 100644 --- a/g/container/gtree/gtree_z_redblack_tree_test.go +++ b/g/container/gtree/gtree_z_redblack_tree_test.go @@ -7,10 +7,13 @@ package gtree_test import ( + "fmt" + "testing" + "github.com/gogf/gf/g/container/gtree" + "github.com/gogf/gf/g/container/gvar" "github.com/gogf/gf/g/test/gtest" "github.com/gogf/gf/g/util/gutil" - "testing" ) func getValue() interface{} { @@ -27,6 +30,7 @@ func Test_RedBlackTree_Basic(t *testing.T) { gtest.Assert(m.Size(), 1) gtest.Assert(m.IsEmpty(), false) + gtest.Assert(m.GetOrSet("key2", "val2"), "val2") gtest.Assert(m.GetOrSet("key2", "val2"), "val2") gtest.Assert(m.SetIfNotExist("key2", "val2"), false) @@ -40,9 +44,14 @@ func Test_RedBlackTree_Basic(t *testing.T) { gtest.AssertIN("val3", m.Values()) gtest.AssertIN("val1", m.Values()) + m.Sets(map[interface{}]interface{}{"key3": "val3", "key1": "val1"}) + m.Flip() gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"}) + m.Flip(gutil.ComparatorString) + gtest.Assert(m.Map(), map[interface{}]interface{}{"key3": "val3", "key1": "val1"}) + m.Clear() gtest.Assert(m.Size(), 0) gtest.Assert(m.IsEmpty(), true) @@ -51,15 +60,47 @@ func Test_RedBlackTree_Basic(t *testing.T) { gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) }) } + func Test_RedBlackTree_Set_Fun(t *testing.T) { - m := gtree.NewRedBlackTree(gutil.ComparatorString) - m.GetOrSetFunc("fun", getValue) - m.GetOrSetFuncLock("funlock", getValue) - gtest.Assert(m.Get("funlock"), 3) - gtest.Assert(m.Get("fun"), 3) - m.GetOrSetFunc("fun", getValue) - gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false) - gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false) + //GetOrSetFunc lock or unlock + gtest.Case(t, func() { + m := gtree.NewRedBlackTree(gutil.ComparatorString) + gtest.Assert(m.GetOrSetFunc("fun", getValue), 3) + gtest.Assert(m.GetOrSetFunc("fun", getValue), 3) + gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3) + gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3) + gtest.Assert(m.Get("funlock"), 3) + gtest.Assert(m.Get("fun"), 3) + }) + //SetIfNotExistFunc lock or unlock + gtest.Case(t, func() { + m := gtree.NewRedBlackTree(gutil.ComparatorString) + gtest.Assert(m.SetIfNotExistFunc("fun", getValue), true) + gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false) + gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), true) + gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false) + gtest.Assert(m.Get("funlock"), 3) + gtest.Assert(m.Get("fun"), 3) + }) + +} + +func Test_RedBlackTree_Get_Set_Var(t *testing.T) { + gtest.Case(t, func() { + m := gtree.NewRedBlackTree(gutil.ComparatorString) + gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), true) + gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), false) + gtest.AssertEQ(m.GetVarOrSet("key1", "val1"), gvar.New("val1", true)) + gtest.AssertEQ(m.GetVar("key1"), gvar.New("val1", true)) + }) + + gtest.Case(t, func() { + m := gtree.NewRedBlackTree(gutil.ComparatorString) + gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true)) + gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true)) + gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true)) + gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true)) + }) } func Test_RedBlackTree_Batch(t *testing.T) { @@ -69,27 +110,61 @@ func Test_RedBlackTree_Batch(t *testing.T) { m.Removes([]interface{}{"key1", 1}) gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"}) } -func Test_RedBlackTree_Iterator(t *testing.T){ - expect := map[interface{}]interface{}{1: 1, "key1": "val1"} + +func Test_RedBlackTree_Iterator(t *testing.T) { + keys := []string{"1", "key1", "key2", "key3", "key4"} + keyLen := len(keys) + index := 0 + + expect := map[interface{}]interface{}{"key4": "val4", 1: 1, "key1": "val1", "key2": "val2", "key3": "val3"} m := gtree.NewRedBlackTreeFrom(gutil.ComparatorString, expect) m.Iterator(func(k interface{}, v interface{}) bool { + gtest.Assert(k, keys[index]) + index++ gtest.Assert(expect[k], v) return true }) - // 断言返回值对遍历控制 - i := 0 - j := 0 - m.Iterator(func(k interface{}, v interface{}) bool { - i++ + + m.IteratorDesc(func(k interface{}, v interface{}) bool { + index-- + gtest.Assert(k, keys[index]) + gtest.Assert(expect[k], v) return true }) - m.Iterator(func(k interface{}, v interface{}) bool { - j++ - return false + + m.Print() + // 断言返回值对遍历控制 + gtest.Case(t, func() { + i := 0 + j := 0 + m.Iterator(func(k interface{}, v interface{}) bool { + i++ + return true + }) + m.Iterator(func(k interface{}, v interface{}) bool { + j++ + return false + }) + gtest.Assert(i, keyLen) + gtest.Assert(j, 1) }) - gtest.Assert(i, 2) - gtest.Assert(j, 1) + + gtest.Case(t, func() { + i := 0 + j := 0 + m.IteratorDesc(func(k interface{}, v interface{}) bool { + i++ + return true + }) + m.IteratorDesc(func(k interface{}, v interface{}) bool { + j++ + return false + }) + gtest.Assert(i, keyLen) + gtest.Assert(j, 1) + }) + } func Test_RedBlackTree_Clone(t *testing.T) { @@ -103,4 +178,78 @@ func Test_RedBlackTree_Clone(t *testing.T) { m_clone.Remove("key1") //修改clone map,原 map 不影响 gtest.AssertIN("key1", m.Keys()) -} \ No newline at end of file +} + +func Test_RedBlackTree_LRNode(t *testing.T) { + expect := map[interface{}]interface{}{"key4": "val4", "key1": "val1", "key2": "val2", "key3": "val3"} + //safe + gtest.Case(t, func() { + m := gtree.NewRedBlackTreeFrom(gutil.ComparatorString, expect) + gtest.Assert(m.Left().Key, "key1") + gtest.Assert(m.Right().Key, "key4") + }) + //unsafe + gtest.Case(t, func() { + m := gtree.NewRedBlackTreeFrom(gutil.ComparatorString, expect, true) + gtest.Assert(m.Left().Key, "key1") + gtest.Assert(m.Right().Key, "key4") + }) +} + +func Test_RedBlackTree_CeilingFloor(t *testing.T) { + expect := map[interface{}]interface{}{ + 20: "val20", + 6: "val6", + 10: "val10", + 12: "val12", + 1: "val1", + 15: "val15", + 19: "val19", + 8: "val8", + 4: "val4"} + //found and eq + gtest.Case(t, func() { + m := gtree.NewRedBlackTreeFrom(gutil.ComparatorInt, expect) + c, cf := m.Ceiling(8) + gtest.Assert(cf, true) + gtest.Assert(c.Value, "val8") + f, ff := m.Floor(20) + gtest.Assert(ff, true) + gtest.Assert(f.Value, "val20") + }) + //found and neq + gtest.Case(t, func() { + m := gtree.NewRedBlackTreeFrom(gutil.ComparatorInt, expect) + c, cf := m.Ceiling(9) + gtest.Assert(cf, true) + gtest.Assert(c.Value, "val10") + f, ff := m.Floor(5) + gtest.Assert(ff, true) + gtest.Assert(f.Value, "val4") + }) + //nofound + gtest.Case(t, func() { + m := gtree.NewRedBlackTreeFrom(gutil.ComparatorInt, expect) + c, cf := m.Ceiling(21) + gtest.Assert(cf, false) + gtest.Assert(c, nil) + f, ff := m.Floor(-1) + gtest.Assert(ff, false) + gtest.Assert(f, nil) + }) +} + +func Test_RedBlackTree_Remove(t *testing.T) { + m := gtree.NewRedBlackTree(gutil.ComparatorInt) + for i := 1; i <= 100; i++ { + m.Set(i, fmt.Sprintf("val%d", i)) + } + expect := m.Map() + gtest.Case(t, func() { + for k, v := range expect { + m1 := m.Clone() + gtest.Assert(m1.Remove(k), v) + gtest.Assert(m1.Remove(k), nil) + } + }) +}