122 lines
3 KiB
Go
122 lines
3 KiB
Go
|
// Copyright (c) 2015-2016 The btcsuite developers
|
||
|
// Use of this source code is governed by an ISC
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
package treap
|
||
|
|
||
|
import (
|
||
|
"encoding/binary"
|
||
|
"encoding/hex"
|
||
|
"math/rand"
|
||
|
"reflect"
|
||
|
"testing"
|
||
|
)
|
||
|
|
||
|
// fromHex converts the passed hex string into a byte slice and will panic if
|
||
|
// there is an error. This is only provided for the hard-coded constants so
|
||
|
// errors in the source code can be detected. It will only (and must only) be
|
||
|
// called for initialization purposes.
|
||
|
func fromHex(s string) []byte {
|
||
|
r, err := hex.DecodeString(s)
|
||
|
if err != nil {
|
||
|
panic("invalid hex in source file: " + s)
|
||
|
}
|
||
|
return r
|
||
|
}
|
||
|
|
||
|
// serializeUint32 returns the big-endian encoding of the passed uint32.
|
||
|
func serializeUint32(ui uint32) []byte {
|
||
|
var ret [4]byte
|
||
|
binary.BigEndian.PutUint32(ret[:], ui)
|
||
|
return ret[:]
|
||
|
}
|
||
|
|
||
|
// TestParentStack ensures the treapParentStack functionality works as intended.
|
||
|
func TestParentStack(t *testing.T) {
|
||
|
t.Parallel()
|
||
|
|
||
|
tests := []struct {
|
||
|
numNodes int
|
||
|
}{
|
||
|
{numNodes: 1},
|
||
|
{numNodes: staticDepth},
|
||
|
{numNodes: staticDepth + 1}, // Test dynamic code paths
|
||
|
}
|
||
|
|
||
|
testLoop:
|
||
|
for i, test := range tests {
|
||
|
nodes := make([]*treapNode, 0, test.numNodes)
|
||
|
for j := 0; j < test.numNodes; j++ {
|
||
|
var key [4]byte
|
||
|
binary.BigEndian.PutUint32(key[:], uint32(j))
|
||
|
node := newTreapNode(key[:], key[:], 0)
|
||
|
nodes = append(nodes, node)
|
||
|
}
|
||
|
|
||
|
// Push all of the nodes onto the parent stack while testing
|
||
|
// various stack properties.
|
||
|
stack := &parentStack{}
|
||
|
for j, node := range nodes {
|
||
|
stack.Push(node)
|
||
|
|
||
|
// Ensure the stack length is the expected value.
|
||
|
if stack.Len() != j+1 {
|
||
|
t.Errorf("Len #%d (%d): unexpected stack "+
|
||
|
"length - got %d, want %d", i, j,
|
||
|
stack.Len(), j+1)
|
||
|
continue testLoop
|
||
|
}
|
||
|
|
||
|
// Ensure the node at each index is the expected one.
|
||
|
for k := 0; k <= j; k++ {
|
||
|
atNode := stack.At(j - k)
|
||
|
if !reflect.DeepEqual(atNode, nodes[k]) {
|
||
|
t.Errorf("At #%d (%d): mismatched node "+
|
||
|
"- got %v, want %v", i, j-k,
|
||
|
atNode, nodes[k])
|
||
|
continue testLoop
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Ensure each popped node is the expected one.
|
||
|
for j := 0; j < len(nodes); j++ {
|
||
|
node := stack.Pop()
|
||
|
expected := nodes[len(nodes)-j-1]
|
||
|
if !reflect.DeepEqual(node, expected) {
|
||
|
t.Errorf("At #%d (%d): mismatched node - "+
|
||
|
"got %v, want %v", i, j, node, expected)
|
||
|
continue testLoop
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Ensure the stack is now empty.
|
||
|
if stack.Len() != 0 {
|
||
|
t.Errorf("Len #%d: stack is not empty - got %d", i,
|
||
|
stack.Len())
|
||
|
continue testLoop
|
||
|
}
|
||
|
|
||
|
// Ensure attempting to retrieve a node at an index beyond the
|
||
|
// stack's length returns nil.
|
||
|
if node := stack.At(2); node != nil {
|
||
|
t.Errorf("At #%d: did not give back nil - got %v", i,
|
||
|
node)
|
||
|
continue testLoop
|
||
|
}
|
||
|
|
||
|
// Ensure attempting to pop a node from an empty stack returns
|
||
|
// nil.
|
||
|
if node := stack.Pop(); node != nil {
|
||
|
t.Errorf("Pop #%d: did not give back nil - got %v", i,
|
||
|
node)
|
||
|
continue testLoop
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func init() {
|
||
|
// Force the same pseudo random numbers for each test run.
|
||
|
rand.Seed(0)
|
||
|
}
|