diff --git a/debug.go b/debug.go index bc46463..2a397fa 100644 --- a/debug.go +++ b/debug.go @@ -76,15 +76,20 @@ func (n *node) fprintBST(w io.Writer, pad string) error { return nil } -// Statistics, returns the maxDepth, average and standard deviation of the nodes. +// statistics, returns the maxDepth, average and standard deviation of the nodes. +// If the skip function is not nil, a true return value defines which nodes must be skipped in the statistics. // // Note: This is for debugging and testing purposes only during development. -func (t Table) statistics() (size int, maxDepth int, average, deviation float64) { +func (t Table) statistics(skip func(netip.Prefix, any, int) bool) (size int, maxDepth int, average, deviation float64) { // key is depth, value is the sum of nodes with this depth depths := make(map[int]int) // closure callback, get the depths, sum up the size cb := func(pfx netip.Prefix, val any, depth int) bool { + if skip != nil && skip(pfx, val, depth) { + return true + } + depths[depth] += 1 size += 1 return true diff --git a/treap_test.go b/treap_test.go index 93ae4b0..b62fc99 100644 --- a/treap_test.go +++ b/treap_test.go @@ -121,6 +121,10 @@ func TestZeroValue(t *testing.T) { if _, _, ok := zeroTable.LookupCIDR(zeroCIDR); ok { t.Errorf("LookupCIDR(), got: %v, want: false", ok) } + + if rtbl := zeroTable.Union(&zeroTable); *rtbl != zeroTable { + t.Errorf("Union(), got: %#v, want: %#v", rtbl, &zeroTable) + } } func TestInsert(t *testing.T) { @@ -534,6 +538,12 @@ func TestUnion(t *testing.T) { t.Errorf("Fprint()\nwant:\n%sgot:\n%s", asTopoStr, rtbl.String()) } + clone := rtbl.Clone() + rtbl.UnionMutable(new(cidrtree.Table)) + if !reflect.DeepEqual(rtbl, clone) { + t.Fatal("UnionMutable with zero value changed original") + } + rtbl3 := rtbl.Union(rtbl2) if rtbl3.String() != asTopoStr { t.Errorf("Fprint()\nwant:\n%sgot:\n%s", asTopoStr, rtbl.String()) diff --git a/whitebox_test.go b/whitebox_test.go index 87f15df..786cb5a 100644 --- a/whitebox_test.go +++ b/whitebox_test.go @@ -18,7 +18,7 @@ func TestFprintBST(t *testing.T) { rtbl.InsertMutable(randPfx4(), nil) rtbl.InsertMutable(randPfx6(), nil) } - size, maxDepth, average, deviation := rtbl.statistics() + size, maxDepth, average, deviation := rtbl.statistics(nil) t.Logf("v4/v6: size: %10d, maxDepth: %4d, average: %3.2f, deviation: %3.2f", size, maxDepth, average, deviation) t.Log() @@ -37,7 +37,7 @@ func TestStatisticsRandom(t *testing.T) { for c := 0; c <= i; c++ { rtbl.InsertMutable(randPfx(), nil) } - size, maxDepth, average, deviation := rtbl.statistics() + size, maxDepth, average, deviation := rtbl.statistics(nil) t.Logf("v4/v6: size: %10d, maxDepth: %4d, average: %3.2f, deviation: %3.2f", size, maxDepth, average, deviation) } } @@ -47,8 +47,29 @@ func TestStatisticsFullTable(t *testing.T) { for _, cidr := range fullTable { rtbl.InsertMutable(cidr, nil) } - size, maxDepth, average, deviation := rtbl.statistics() - t.Logf("FullTable: size: %10d, maxDepth: %4d, average: %3.2f, deviation: %3.2f", size, maxDepth, average, deviation) + + skip4 := func(pfx netip.Prefix, val any, depth int) bool { + if pfx.Addr().Is4() { + return true + } + return false + } + + skip6 := func(pfx netip.Prefix, val any, depth int) bool { + if !pfx.Addr().Is4() { + return true + } + return false + } + + size, maxDepth, average, deviation := rtbl.statistics(skip6) + t.Logf("FullTableV4: size: %10d, maxDepth: %4d, average: %3.2f, deviation: %3.2f", size, maxDepth, average, deviation) + + size, maxDepth, average, deviation = rtbl.statistics(skip4) + t.Logf("FullTableV6: size: %10d, maxDepth: %4d, average: %3.2f, deviation: %3.2f", size, maxDepth, average, deviation) + + size, maxDepth, average, deviation = rtbl.statistics(nil) + t.Logf("FullTable: size: %10d, maxDepth: %4d, average: %3.2f, deviation: %3.2f", size, maxDepth, average, deviation) } func TestLPMRandom(t *testing.T) { @@ -57,7 +78,7 @@ func TestLPMRandom(t *testing.T) { for c := 0; c <= i; c++ { rtbl.InsertMutable(randPfx(), nil) } - size, maxDepth, average, _ := rtbl.statistics() + size, maxDepth, average, _ := rtbl.statistics(nil) var lpm netip.Prefix var depth int @@ -82,7 +103,7 @@ func TestLPMFullTableWithDefaultRoutes(t *testing.T) { rtbl.InsertMutable(dg4, nil) rtbl.InsertMutable(dg6, nil) - size, maxDepth, average, deviation := rtbl.statistics() + size, maxDepth, average, deviation := rtbl.statistics(nil) t.Logf("FullTable: size: %10d, maxDepth: %4d, average: %3.2f, deviation: %3.2f", size, maxDepth, average, deviation) t.Log()