mirror of
https://github.com/weaveworks/scope.git
synced 2026-03-02 17:50:39 +00:00
Add vendored deps for tracer.
This commit is contained in:
22
experimental/tracer/vendor/github.com/msackman/skiplist/LICENSE
generated
vendored
Normal file
22
experimental/tracer/vendor/github.com/msackman/skiplist/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Matthew Sackman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
2
experimental/tracer/vendor/github.com/msackman/skiplist/README.md
generated
vendored
Normal file
2
experimental/tracer/vendor/github.com/msackman/skiplist/README.md
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
Skiplist implementation for Go. Comes with tests. Currently no docs,
|
||||
but it's pretty obvious stuff.
|
||||
429
experimental/tracer/vendor/github.com/msackman/skiplist/skiplist.go
generated
vendored
Normal file
429
experimental/tracer/vendor/github.com/msackman/skiplist/skiplist.go
generated
vendored
Normal file
@@ -0,0 +1,429 @@
|
||||
package skiplist
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/rand"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
p = 0.3
|
||||
defaultDepth = 2
|
||||
)
|
||||
|
||||
type Comparable interface {
|
||||
LessThan(Comparable) bool
|
||||
Equal(Comparable) bool
|
||||
}
|
||||
|
||||
type SkipList struct {
|
||||
length uint
|
||||
terminus *Node
|
||||
levelProbabilities []float32
|
||||
curCapacity uint
|
||||
curDepth uint
|
||||
nodes []Node
|
||||
localRand *rand.Rand
|
||||
}
|
||||
|
||||
type Node struct {
|
||||
Key Comparable
|
||||
Value interface{}
|
||||
heightRand float32
|
||||
prev *Node
|
||||
nexts []*Node
|
||||
skiplist *SkipList
|
||||
}
|
||||
|
||||
func New(rng *rand.Rand) *SkipList {
|
||||
depth := defaultDepth
|
||||
|
||||
terminus := &Node{
|
||||
heightRand: 0,
|
||||
nexts: make([]*Node, depth),
|
||||
}
|
||||
terminus.prev = terminus
|
||||
for idx := 0; idx < len(terminus.nexts); idx++ {
|
||||
terminus.nexts[idx] = terminus
|
||||
}
|
||||
s := &SkipList{
|
||||
length: 0,
|
||||
terminus: terminus,
|
||||
curDepth: uint(depth),
|
||||
localRand: rng,
|
||||
}
|
||||
s.levelProbabilities = []float32{p}
|
||||
terminus.skiplist = s
|
||||
s.determineCapacity()
|
||||
|
||||
// s.validate()
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *SkipList) determineCapacity() {
|
||||
base := float64(1.0) / p
|
||||
capacity := math.Pow(base, float64(s.curDepth))
|
||||
s.curCapacity = uint(math.Floor(capacity))
|
||||
}
|
||||
|
||||
func (s *SkipList) chooseNumLevels() (float32, int) {
|
||||
r := s.localRand.Float32()
|
||||
max := len(s.levelProbabilities)
|
||||
for idx := 0; idx < max; idx++ {
|
||||
if r > s.levelProbabilities[idx] {
|
||||
return r, idx + 1
|
||||
}
|
||||
}
|
||||
return r, max + 1
|
||||
}
|
||||
|
||||
func (s *SkipList) ensureCapacity() {
|
||||
// defer s.validate()
|
||||
if s.length < s.curCapacity {
|
||||
return
|
||||
}
|
||||
|
||||
threshold := p * s.levelProbabilities[s.curDepth-2]
|
||||
s.curDepth++
|
||||
s.levelProbabilities = append(s.levelProbabilities, threshold)
|
||||
|
||||
s.determineCapacity()
|
||||
|
||||
// cur and next are just used to walk through the list at lvl. prev
|
||||
// records the last node that made it up to the new level.
|
||||
cur := s.terminus
|
||||
lvl := len(cur.nexts) - 1
|
||||
prev := cur
|
||||
for {
|
||||
next := cur.nexts[lvl]
|
||||
if cur.heightRand <= threshold {
|
||||
cur.nexts = append(cur.nexts, s.terminus)
|
||||
prev.nexts[lvl+1] = cur
|
||||
prev = cur
|
||||
}
|
||||
if next == s.terminus {
|
||||
break
|
||||
} else {
|
||||
cur = next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SkipList) getNode() *Node {
|
||||
l := len(s.nodes)
|
||||
if l == 0 {
|
||||
l = int(s.curCapacity)
|
||||
s.nodes = make([]Node, l)
|
||||
}
|
||||
l--
|
||||
n := &s.nodes[l]
|
||||
s.nodes = s.nodes[:l]
|
||||
return n
|
||||
}
|
||||
|
||||
func (s *SkipList) getEqOrLessThan(cur *Node, k Comparable, captureDescent bool) (*Node, []*Node) {
|
||||
// defer s.validate()
|
||||
|
||||
if s.length == 0 {
|
||||
return s.terminus, nil
|
||||
}
|
||||
if cur != s.terminus {
|
||||
if k.Equal(cur.Key) {
|
||||
return cur, nil
|
||||
}
|
||||
if k.LessThan(cur.Key) {
|
||||
return s.getEqOrLessThan(s.terminus, k, captureDescent)
|
||||
}
|
||||
}
|
||||
// 1. Travel, not-descending, as far as possible
|
||||
lvl := len(cur.nexts) - 1
|
||||
for {
|
||||
n := cur.nexts[lvl]
|
||||
if n == s.terminus {
|
||||
break
|
||||
}
|
||||
if n.Key.LessThan(k) {
|
||||
cur = n
|
||||
lvl = len(cur.nexts) - 1
|
||||
} else if n.Key.Equal(k) {
|
||||
return n, nil
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// 2. Now descend as needed
|
||||
var descent []*Node
|
||||
if captureDescent {
|
||||
descent = make([]*Node, lvl+1)
|
||||
descent[lvl] = cur
|
||||
}
|
||||
for lvl--; lvl >= 0; lvl-- {
|
||||
for {
|
||||
n := cur.nexts[lvl]
|
||||
if n == s.terminus {
|
||||
break
|
||||
}
|
||||
if n.Key.LessThan(k) {
|
||||
cur = n
|
||||
} else if n.Key.Equal(k) {
|
||||
return n, descent
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
if captureDescent {
|
||||
descent[lvl] = cur
|
||||
}
|
||||
}
|
||||
return cur, descent
|
||||
}
|
||||
|
||||
func (s *SkipList) insert(cur *Node, k Comparable, v interface{}, n *Node) *Node {
|
||||
// defer s.validate()
|
||||
|
||||
// do this first even though we may not need to - if we do it after
|
||||
// the getEqOrLessThan call, we may break descent.
|
||||
s.ensureCapacity()
|
||||
cur, descent := s.getEqOrLessThan(cur, k, true)
|
||||
if cur != s.terminus && cur.Key.Equal(k) {
|
||||
cur.Value = v
|
||||
return cur
|
||||
}
|
||||
// We didn't find k, so cur will be the node immediately prior to
|
||||
// where k should go.
|
||||
heightRand, height := s.chooseNumLevels()
|
||||
if n == nil {
|
||||
n = s.getNode()
|
||||
}
|
||||
n.Key = k
|
||||
n.Value = v
|
||||
n.heightRand = heightRand
|
||||
n.nexts = make([]*Node, height)
|
||||
n.prev = cur
|
||||
n.skiplist = s
|
||||
|
||||
if len(cur.nexts) >= len(n.nexts) {
|
||||
for idx := 0; idx < len(n.nexts); idx++ {
|
||||
n.nexts[idx] = cur.nexts[idx]
|
||||
cur.nexts[idx] = n
|
||||
}
|
||||
} else {
|
||||
// Descent may capture only part of the path: it may be shorter
|
||||
// than levels (in the case where the original cur is !=
|
||||
// s.terminus) and we reached the correct location without
|
||||
// travelling up very far. However, because we didn't find k, we
|
||||
// know that all the "lower" levels of descent will be populated
|
||||
// (where "lower" is "closer to [0]"), so we just need to fill in
|
||||
// the "top".
|
||||
if len(n.nexts) > len(descent) {
|
||||
_, extra := s.getEqOrLessThan(s.terminus, descent[len(descent)-1].Key, true)
|
||||
// Aside: because we know we'll find that Key, all the lower
|
||||
// indices of extra will be nil.
|
||||
descent = append(descent, extra[len(descent):]...)
|
||||
}
|
||||
for idx := 0; idx < len(n.nexts); idx++ {
|
||||
n.nexts[idx] = descent[idx].nexts[idx]
|
||||
descent[idx].nexts[idx] = n
|
||||
}
|
||||
}
|
||||
n._next().prev = n
|
||||
s.length++
|
||||
return n
|
||||
}
|
||||
|
||||
func (s *SkipList) remove(cur *Node, k Comparable) interface{} {
|
||||
// defer s.validate()
|
||||
|
||||
n, _ := s.getEqOrLessThan(cur, k, false)
|
||||
if n == s.terminus || !n.Key.Equal(k) {
|
||||
return nil
|
||||
}
|
||||
s.removeNode(n)
|
||||
n.nullify()
|
||||
return n.Value
|
||||
}
|
||||
|
||||
func (s *SkipList) removeNode(n *Node) {
|
||||
// defer s.validate()
|
||||
|
||||
p := n.prev
|
||||
n._next().prev = p
|
||||
s.length--
|
||||
for idx := 0; idx < len(p.nexts) && idx < len(n.nexts); idx++ {
|
||||
p.nexts[idx] = n.nexts[idx]
|
||||
}
|
||||
if len(p.nexts) < len(n.nexts) {
|
||||
_, descent := s.getEqOrLessThan(s.terminus, p.Key, true)
|
||||
// because we know we're going to find Key, the lower indices
|
||||
// of descent will be nil. But we know p == n.prev, so all of
|
||||
// those pointers will be to n anyway, which we've already
|
||||
// dealt with in the previous loop.
|
||||
for idx := len(p.nexts); idx < len(n.nexts); idx++ {
|
||||
descent[idx].nexts[idx] = n.nexts[idx]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SkipList) reposition(cur *Node, k Comparable) {
|
||||
// defer s.validate()
|
||||
|
||||
needsMove := false
|
||||
if cur != s.terminus {
|
||||
if cur.prev != s.terminus && !cur.prev.Key.LessThan(k) {
|
||||
needsMove = true
|
||||
} else if n := cur._next(); n != s.terminus && !k.LessThan(n.Key) {
|
||||
needsMove = true
|
||||
}
|
||||
}
|
||||
if needsMove {
|
||||
s.removeNode(cur)
|
||||
cur.Key = k
|
||||
s.insert(cur.prev, cur.Key, cur.Value, cur)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SkipList) First() *Node {
|
||||
return s.terminus.Next()
|
||||
}
|
||||
|
||||
func (s *SkipList) Last() *Node {
|
||||
return s.terminus.Prev()
|
||||
}
|
||||
|
||||
func (s *SkipList) Insert(k Comparable, v interface{}) *Node {
|
||||
return s.insert(s.terminus, k, v, nil)
|
||||
}
|
||||
|
||||
func (s *SkipList) Get(k Comparable) *Node {
|
||||
return s.terminus.Get(k)
|
||||
}
|
||||
|
||||
func (s *SkipList) Remove(k Comparable) interface{} {
|
||||
return s.remove(s.terminus, k)
|
||||
}
|
||||
|
||||
func (s *SkipList) Len() uint {
|
||||
return s.length
|
||||
}
|
||||
|
||||
// NB: this destroys t. Do not use t after this.
|
||||
func (s *SkipList) Merge(t *SkipList) {
|
||||
// defer s.validate()
|
||||
|
||||
cur := s.terminus
|
||||
for n := t.First(); n != nil; {
|
||||
m := n.Next() // need to save this out before we destroy it in the insert
|
||||
cur = s.insert(cur, n.Key, n.Value, n)
|
||||
n = m
|
||||
}
|
||||
}
|
||||
|
||||
func (s *SkipList) validate() {
|
||||
visited := make(map[*Node]bool, int(s.length))
|
||||
cur := s.terminus
|
||||
visited[cur] = true
|
||||
l := uint(0)
|
||||
for {
|
||||
if cur != s.terminus {
|
||||
l++
|
||||
}
|
||||
if cur._next().prev != cur {
|
||||
panic(fmt.Sprintf("Node (%v) has next pointer to %v, which has prev pointer to %v", cur, cur._next(), cur._next().prev))
|
||||
}
|
||||
if cur.prev._next() != cur {
|
||||
panic(fmt.Sprintf("Node (%v) has prev pointer to %v, which has next pointer to %v", cur, cur.prev, cur.prev._next()))
|
||||
}
|
||||
for h, n := range cur.nexts {
|
||||
if h >= len(n.nexts) {
|
||||
panic(fmt.Sprintf("Node (%v) has next pointer at level %v pointing down to node (%v) which has %v height", cur, h, n, len(n.nexts)))
|
||||
}
|
||||
}
|
||||
n := cur._next()
|
||||
if n == s.terminus {
|
||||
break
|
||||
}
|
||||
if visited[n] {
|
||||
panic(fmt.Sprintf("Node (%v) has next as %v which is already visited!", cur, n))
|
||||
}
|
||||
if cur != s.terminus && !cur.Key.LessThan(n.Key) {
|
||||
panic(fmt.Sprintf("Node keys in wrong order: expecting %v < %v", cur.Key, n.Key))
|
||||
}
|
||||
if n.prev != cur {
|
||||
panic(fmt.Sprintf("Node (%v) has next (%v) which does not point back correctly", cur, n))
|
||||
}
|
||||
cur = n
|
||||
}
|
||||
if l != s.length {
|
||||
panic(fmt.Sprintf("length is wrong: counted %v but length is %v", l, s.length))
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) Get(k Comparable) *Node {
|
||||
m, _ := n.skiplist.getEqOrLessThan(n, k, false)
|
||||
if m != n.skiplist.terminus && m.Key.Equal(k) {
|
||||
return m
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) Insert(k Comparable, v interface{}) *Node {
|
||||
return n.skiplist.insert(n, k, v, nil)
|
||||
}
|
||||
|
||||
func (n *Node) Remove() interface{} {
|
||||
return n.skiplist.remove(n, n.Key)
|
||||
}
|
||||
|
||||
func (n *Node) _next() *Node {
|
||||
return n.nexts[0]
|
||||
}
|
||||
|
||||
func (n *Node) Next() *Node {
|
||||
if m := n.nexts[0]; m != n.skiplist.terminus {
|
||||
return m
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) Prev() *Node {
|
||||
if m := n.prev; m != n.skiplist.terminus {
|
||||
return m
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) Reposition(k Comparable) {
|
||||
n.skiplist.reposition(n, k)
|
||||
}
|
||||
|
||||
func (n *Node) nullify() {
|
||||
// this is called when n is removed from the skiplist. It's really
|
||||
// just to ensure that if someone has a reference to n lying
|
||||
// around, they can't use it.
|
||||
n.prev = nil
|
||||
n.nexts = nil
|
||||
n.skiplist = nil
|
||||
}
|
||||
|
||||
func (s *SkipList) String() string {
|
||||
strs := make([]string, 1, s.length+1)
|
||||
strs[0] = fmt.Sprint(s.terminus)
|
||||
for cur := s.terminus._next(); cur != s.terminus; cur = cur._next() {
|
||||
strs = append(strs, fmt.Sprint(cur))
|
||||
}
|
||||
return fmt.Sprintf("Skiplist of length %v (counted: %v), levelProbabilities %v, and nodes:\n\t[%v]",
|
||||
s.length, len(strs)-1, s.levelProbabilities, strings.Join(strs, ",\n\t "))
|
||||
}
|
||||
|
||||
func (n *Node) String() string {
|
||||
strs := make([]string, len(n.nexts))
|
||||
for idx := 0; idx < len(strs); idx++ {
|
||||
strs[idx] = fmt.Sprint(n.nexts[idx].Key)
|
||||
}
|
||||
return fmt.Sprintf("%v -> %v (nexts: [%v])", n.Key, n.Value, strings.Join(strs, ", "))
|
||||
}
|
||||
315
experimental/tracer/vendor/github.com/msackman/skiplist/skiplist_test.go
generated
vendored
Normal file
315
experimental/tracer/vendor/github.com/msackman/skiplist/skiplist_test.go
generated
vendored
Normal file
@@ -0,0 +1,315 @@
|
||||
package skiplist
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type intKey int
|
||||
|
||||
func (sk intKey) LessThan(b Comparable) bool {
|
||||
return sk < b.(intKey)
|
||||
}
|
||||
|
||||
func (sk intKey) Equal(b Comparable) bool {
|
||||
return sk == b.(intKey)
|
||||
}
|
||||
|
||||
const (
|
||||
keyValsLen = 1000000
|
||||
)
|
||||
|
||||
var (
|
||||
rng = rand.New(rand.NewSource(0))
|
||||
keyVals = make(map[intKey]string)
|
||||
indices = make([]intKey, keyValsLen)
|
||||
)
|
||||
|
||||
func TestAddFromEmptyRoot(t *testing.T) {
|
||||
for idx := 0; idx < 10; idx++ {
|
||||
s := New(rng)
|
||||
for idy := 0; idy < idx; idy++ {
|
||||
k := indices[idy]
|
||||
v := keyVals[k]
|
||||
n := s.Insert(k, v)
|
||||
if n.Key != k || n.Value != v {
|
||||
t.Fatal("Key or Value of inserted pair changed!", k, v, n)
|
||||
}
|
||||
if m := s.Get(k); n != m {
|
||||
t.Fatal("Node changed for just inserted value:", n, m)
|
||||
}
|
||||
if s.Len() != uint(idy+1) {
|
||||
t.Fatal("Incorrect length")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddFromEmptyRel(t *testing.T) {
|
||||
for idx := 0; idx < 10; idx++ {
|
||||
s := New(rng)
|
||||
var n *Node
|
||||
for idy := 0; idy < idx; idy++ {
|
||||
k := indices[idy]
|
||||
v := keyVals[k]
|
||||
if n == nil {
|
||||
n = s.Insert(k, v)
|
||||
} else {
|
||||
n = n.Insert(k, v)
|
||||
}
|
||||
if n.Key != k || n.Value != v {
|
||||
t.Fatal("Key or Value of inserted pair changed!", k, v, n)
|
||||
}
|
||||
if m := n.Get(k); n != m {
|
||||
t.Fatal("Node changed for just inserted value:", n, m)
|
||||
}
|
||||
if p := n.Prev(); p != nil {
|
||||
if m := p.Get(k); n != m {
|
||||
t.Fatal("Node changed for just inserted value:", n, m)
|
||||
}
|
||||
}
|
||||
if s.Len() != uint(idy+1) {
|
||||
t.Fatal("Incorrect length")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDupInsert(t *testing.T) {
|
||||
s := New(rng)
|
||||
for idx := 0; idx < 10; idx++ {
|
||||
for idy := 0; idy < idx; idy++ {
|
||||
k := indices[idy]
|
||||
v := keyVals[k]
|
||||
if n := s.Insert(k, v); n.Key != k || n.Value != v {
|
||||
t.Fatal("Key or Value of inserted pair changed!", k, v, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMissingEmpty(t *testing.T) {
|
||||
s := New(rng)
|
||||
for idx := 0; idx < 10; idx++ {
|
||||
k := indices[idx]
|
||||
if n := s.Get(k); n != nil {
|
||||
t.Fatal("Expected not to find elem")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMissingNonEmpty(t *testing.T) {
|
||||
s := New(rng)
|
||||
for idx := 0; idx < 20; idx++ {
|
||||
k := indices[idx]
|
||||
v := keyVals[k]
|
||||
if idx%2 == 0 {
|
||||
s.Insert(k, v)
|
||||
} else {
|
||||
if n := s.Get(k); n != nil {
|
||||
t.Fatal("Expected not to find elem")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveRoot(t *testing.T) {
|
||||
s := New(rng)
|
||||
for idx := 0; idx < 20; idx++ {
|
||||
k := indices[idx]
|
||||
v := keyVals[k]
|
||||
s.Insert(k, v)
|
||||
}
|
||||
for idx := 0; idx < 20; idx++ {
|
||||
k := indices[idx]
|
||||
v := keyVals[k]
|
||||
if u := s.Remove(k); u != v {
|
||||
t.Fatal("Wrong value returned:", u, v)
|
||||
}
|
||||
if int(s.Len()) != 19-idx {
|
||||
t.Fatal("Wrong length")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveSelf(t *testing.T) {
|
||||
s := New(rng)
|
||||
ns := []*Node{}
|
||||
for idx := 0; idx < 20; idx++ {
|
||||
k := indices[idx]
|
||||
v := keyVals[k]
|
||||
ns = append(ns, s.Insert(k, v))
|
||||
}
|
||||
for idx, n := range ns {
|
||||
k := indices[idx]
|
||||
v := keyVals[k]
|
||||
if u := n.Remove(); u != v {
|
||||
t.Fatal("Wrong value returned:", u, v)
|
||||
}
|
||||
if int(s.Len()) != len(ns)-idx-1 {
|
||||
t.Fatal("Wrong length")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveMissing(t *testing.T) {
|
||||
s := New(rng)
|
||||
for idx := 0; idx < 20; idx++ {
|
||||
k := indices[idx]
|
||||
v := keyVals[k]
|
||||
s.Insert(k, v)
|
||||
}
|
||||
for idx := 0; idx < 20; idx++ {
|
||||
for idy := 0; idy < idx; idy++ {
|
||||
k := indices[idy]
|
||||
v := keyVals[k]
|
||||
u := s.Remove(k)
|
||||
if idy+1 == idx {
|
||||
if u != v {
|
||||
t.Fatal("Wrong value returned:", u, v)
|
||||
}
|
||||
} else {
|
||||
if u != nil {
|
||||
t.Fatal("Wrong value returned - expected nil:", u)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if s.Len() != 1 {
|
||||
t.Fatal("Wrong length")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFirstLast(t *testing.T) {
|
||||
s := New(rng)
|
||||
if s.First() != nil || s.Last() != nil {
|
||||
t.Fatal("Expected nil for First and Last on empty list")
|
||||
}
|
||||
var min, max intKey
|
||||
for idx := 0; idx < 200; idx++ {
|
||||
k := indices[idx]
|
||||
v := keyVals[k]
|
||||
s.Insert(k, v)
|
||||
if idx == 0 {
|
||||
min, max = k, k
|
||||
} else {
|
||||
if k < min {
|
||||
min = k
|
||||
}
|
||||
if k > max {
|
||||
max = k
|
||||
}
|
||||
}
|
||||
}
|
||||
if f := s.First(); f.Key != min {
|
||||
t.Fatal("Did not get minimum key back for first", min, f)
|
||||
}
|
||||
if l := s.Last(); l.Key != max {
|
||||
t.Fatal("Did not get maximum key back for last", max, l)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
s0 := New(rng)
|
||||
s1 := New(rng)
|
||||
lim := 1000
|
||||
for idx := 0; idx < lim; idx++ {
|
||||
if idx%2 == 0 {
|
||||
s0.Insert(intKey(idx), idx)
|
||||
} else {
|
||||
s1.Insert(intKey(idx), idx)
|
||||
}
|
||||
}
|
||||
s0.Merge(s1)
|
||||
if int(s0.Len()) != lim {
|
||||
t.Fatal("Wrong len after merge", s0.Len())
|
||||
}
|
||||
cur := s0.First()
|
||||
for idx := 0; idx < lim; idx++ {
|
||||
if cur.Value.(int) != idx {
|
||||
t.Fatal("Wrong value: ", cur.Value)
|
||||
}
|
||||
if cur != s0.Get(cur.Key) {
|
||||
t.Fatal("Internal failure: ", cur)
|
||||
}
|
||||
cur = cur.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func TestReposition(t *testing.T) {
|
||||
s := New(rng)
|
||||
lim := 200
|
||||
for idx := 0; idx < lim; idx++ {
|
||||
s.Insert(intKey(idx*5), idx)
|
||||
}
|
||||
for idx := lim - 1; idx >= 0; idx-- {
|
||||
n := s.Get(intKey(idx * 5))
|
||||
if n == nil {
|
||||
t.Fatal("Unable to find node")
|
||||
}
|
||||
n.Reposition(intKey((idx * 5) - 11))
|
||||
}
|
||||
n := s.First()
|
||||
for idx := 0; idx < lim; idx++ {
|
||||
if n.Value != idx {
|
||||
t.Fatal("Wrong value", idx, n)
|
||||
}
|
||||
n = n.Next()
|
||||
}
|
||||
if n != nil {
|
||||
t.Fatal("Too many values!")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAdd08192(b *testing.B) { benchmarkAdd(8192, b) }
|
||||
func BenchmarkAdd16384(b *testing.B) { benchmarkAdd(16384, b) }
|
||||
func BenchmarkAdd32768(b *testing.B) { benchmarkAdd(32768, b) }
|
||||
func BenchmarkAdd65536(b *testing.B) { benchmarkAdd(65536, b) }
|
||||
|
||||
func benchmarkAdd(initial int, b *testing.B) {
|
||||
s := populate(New(rng), 0, initial)
|
||||
b.ResetTimer()
|
||||
populateFast(s, initial, b.N)
|
||||
}
|
||||
|
||||
func BenchmarkGet08192(b *testing.B) { benchmarkGet(8192, b) }
|
||||
func BenchmarkGet16384(b *testing.B) { benchmarkGet(16384, b) }
|
||||
func BenchmarkGet32768(b *testing.B) { benchmarkGet(32768, b) }
|
||||
func BenchmarkGet65536(b *testing.B) { benchmarkGet(65536, b) }
|
||||
|
||||
func benchmarkGet(initial int, b *testing.B) {
|
||||
s := populate(New(rng), 0, initial)
|
||||
b.ResetTimer()
|
||||
for idx := 0; idx < b.N; idx++ {
|
||||
s.Get(indices[idx%initial])
|
||||
}
|
||||
}
|
||||
|
||||
func populate(s *SkipList, offset, lim int) *SkipList {
|
||||
for idx := 0; idx < lim; idx++ {
|
||||
k := indices[(offset+idx)%len(indices)]
|
||||
v := keyVals[k]
|
||||
s.Insert(k, v)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func populateFast(s *SkipList, offset, lim int) *SkipList {
|
||||
for idx := 0; idx < lim; idx++ {
|
||||
n := idx + offset
|
||||
s.Insert(intKey(n), n)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
for idx := 0; idx < keyValsLen; idx++ {
|
||||
keyVals[intKey(idx)] = strconv.FormatInt(int64(idx), 3)
|
||||
}
|
||||
for idx, k := range rand.Perm(keyValsLen) {
|
||||
indices[idx] = intKey(k)
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
11
experimental/tracer/vendor/manifest
vendored
Normal file
11
experimental/tracer/vendor/manifest
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"version": 0,
|
||||
"dependencies": [
|
||||
{
|
||||
"importpath": "github.com/msackman/skiplist",
|
||||
"repository": "https://github.com/msackman/skiplist",
|
||||
"revision": "57733164b18444c51f63e9a80f1693961dde8036",
|
||||
"branch": "master"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user