| // Copyright 2016 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package ssa |
| |
| import ( |
| "fmt" |
| "testing" |
| ) |
| |
| type sstring string |
| |
| func (s sstring) String() string { |
| return string(s) |
| } |
| |
| // wellFormed ensures that a red-black tree meets |
| // all of its invariants and returns a string identifying |
| // the first problem encountered. If there is no problem |
| // then the returned string is empty. The size is also |
| // returned to allow comparison of calculated tree size |
| // with expected. |
| func (t *RBTint32) wellFormed() (s string, i int) { |
| if t.root == nil { |
| s = "" |
| i = 0 |
| return |
| } |
| return t.root.wellFormedSubtree(nil, -0x80000000, 0x7fffffff) |
| } |
| |
| // wellFormedSubtree ensures that a red-black subtree meets |
| // all of its invariants and returns a string identifying |
| // the first problem encountered. If there is no problem |
| // then the returned string is empty. The size is also |
| // returned to allow comparison of calculated tree size |
| // with expected. |
| func (t *node32) wellFormedSubtree(parent *node32, min, max int32) (s string, i int) { |
| i = -1 // initialize to a failing value |
| s = "" // s is the reason for failure; empty means okay. |
| |
| if t.parent != parent { |
| s = "t.parent != parent" |
| return |
| } |
| |
| if min >= t.key { |
| s = "min >= t.key" |
| return |
| } |
| |
| if max <= t.key { |
| s = "max <= t.key" |
| return |
| } |
| |
| l := t.left |
| r := t.right |
| if l == nil && r == nil { |
| if t.rank != rankLeaf { |
| s = "leaf rank wrong" |
| return |
| } |
| } |
| if l != nil { |
| if t.rank < l.rank { |
| s = "t.rank < l.rank" |
| } else if t.rank > 1+l.rank { |
| s = "t.rank > 1+l.rank" |
| } else if t.rank <= l.maxChildRank() { |
| s = "t.rank <= l.maxChildRank()" |
| } else if t.key <= l.key { |
| s = "t.key <= l.key" |
| } |
| if s != "" { |
| return |
| } |
| } else { |
| if t.rank != 1 { |
| s = "t w/ left nil has rank != 1" |
| return |
| } |
| } |
| if r != nil { |
| if t.rank < r.rank { |
| s = "t.rank < r.rank" |
| } else if t.rank > 1+r.rank { |
| s = "t.rank > 1+r.rank" |
| } else if t.rank <= r.maxChildRank() { |
| s = "t.rank <= r.maxChildRank()" |
| } else if t.key >= r.key { |
| s = "t.key >= r.key" |
| } |
| if s != "" { |
| return |
| } |
| } else { |
| if t.rank != 1 { |
| s = "t w/ right nil has rank != 1" |
| return |
| } |
| } |
| ii := 1 |
| if l != nil { |
| res, il := l.wellFormedSubtree(t, min, t.key) |
| if res != "" { |
| s = "L." + res |
| return |
| } |
| ii += il |
| } |
| if r != nil { |
| res, ir := r.wellFormedSubtree(t, t.key, max) |
| if res != "" { |
| s = "R." + res |
| return |
| } |
| ii += ir |
| } |
| i = ii |
| return |
| } |
| |
| func (t *RBTint32) DebugString() string { |
| if t.root == nil { |
| return "" |
| } |
| return t.root.DebugString() |
| } |
| |
| // DebugString prints the tree with nested information |
| // to allow an eyeball check on the tree balance. |
| func (t *node32) DebugString() string { |
| s := "" |
| if t.left != nil { |
| s = s + "[" |
| s = s + t.left.DebugString() |
| s = s + "]" |
| } |
| s = s + fmt.Sprintf("%v=%v:%d", t.key, t.data, t.rank) |
| if t.right != nil { |
| s = s + "[" |
| s = s + t.right.DebugString() |
| s = s + "]" |
| } |
| return s |
| } |
| |
| func allRBT32Ops(te *testing.T, x []int32) { |
| t := &RBTint32{} |
| for i, d := range x { |
| x[i] = d + d // Double everything for glb/lub testing |
| } |
| |
| // fmt.Printf("Inserting double of %v", x) |
| k := 0 |
| min := int32(0x7fffffff) |
| max := int32(-0x80000000) |
| for _, d := range x { |
| if d < min { |
| min = d |
| } |
| |
| if d > max { |
| max = d |
| } |
| |
| t.Insert(d, sstring(fmt.Sprintf("%v", d))) |
| k++ |
| s, i := t.wellFormed() |
| if i != k { |
| te.Errorf("Wrong tree size %v, expected %v for %v", i, k, t.DebugString()) |
| } |
| if s != "" { |
| te.Errorf("Tree consistency problem at %v", s) |
| return |
| } |
| } |
| |
| oops := false |
| |
| for _, d := range x { |
| s := fmt.Sprintf("%v", d) |
| f := t.Find(d) |
| |
| // data |
| if s != fmt.Sprintf("%v", f) { |
| te.Errorf("s(%v) != f(%v)", s, f) |
| oops = true |
| } |
| } |
| |
| if !oops { |
| for _, d := range x { |
| s := fmt.Sprintf("%v", d) |
| |
| kg, g := t.Glb(d + 1) |
| kge, ge := t.GlbEq(d) |
| kl, l := t.Lub(d - 1) |
| kle, le := t.LubEq(d) |
| |
| // keys |
| if d != kg { |
| te.Errorf("d(%v) != kg(%v)", d, kg) |
| } |
| if d != kl { |
| te.Errorf("d(%v) != kl(%v)", d, kl) |
| } |
| if d != kge { |
| te.Errorf("d(%v) != kge(%v)", d, kge) |
| } |
| if d != kle { |
| te.Errorf("d(%v) != kle(%v)", d, kle) |
| } |
| // data |
| if s != fmt.Sprintf("%v", g) { |
| te.Errorf("s(%v) != g(%v)", s, g) |
| } |
| if s != fmt.Sprintf("%v", l) { |
| te.Errorf("s(%v) != l(%v)", s, l) |
| } |
| if s != fmt.Sprintf("%v", ge) { |
| te.Errorf("s(%v) != ge(%v)", s, ge) |
| } |
| if s != fmt.Sprintf("%v", le) { |
| te.Errorf("s(%v) != le(%v)", s, le) |
| } |
| } |
| |
| for _, d := range x { |
| s := fmt.Sprintf("%v", d) |
| kge, ge := t.GlbEq(d + 1) |
| kle, le := t.LubEq(d - 1) |
| if d != kge { |
| te.Errorf("d(%v) != kge(%v)", d, kge) |
| } |
| if d != kle { |
| te.Errorf("d(%v) != kle(%v)", d, kle) |
| } |
| if s != fmt.Sprintf("%v", ge) { |
| te.Errorf("s(%v) != ge(%v)", s, ge) |
| } |
| if s != fmt.Sprintf("%v", le) { |
| te.Errorf("s(%v) != le(%v)", s, le) |
| } |
| } |
| |
| kg, g := t.Glb(min) |
| kge, ge := t.GlbEq(min - 1) |
| kl, l := t.Lub(max) |
| kle, le := t.LubEq(max + 1) |
| fmin := t.Find(min - 1) |
| fmax := t.Find(min + 11) |
| |
| if kg != 0 || kge != 0 || kl != 0 || kle != 0 { |
| te.Errorf("Got non-zero-key for missing query") |
| } |
| |
| if g != nil || ge != nil || l != nil || le != nil || fmin != nil || fmax != nil { |
| te.Errorf("Got non-error-data for missing query") |
| } |
| |
| } |
| } |
| |
| func TestAllRBTreeOps(t *testing.T) { |
| allRBT32Ops(t, []int32{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}) |
| allRBT32Ops(t, []int32{22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 3, 2, 1, 25, 24, 23, 12, 11, 10, 9, 8, 7, 6, 5, 4}) |
| allRBT32Ops(t, []int32{25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}) |
| allRBT32Ops(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24}) |
| allRBT32Ops(t, []int32{1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2}) |
| allRBT32Ops(t, []int32{24, 22, 20, 18, 16, 14, 12, 10, 8, 6, 4, 2, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25}) |
| } |