common/prque: pull in tests and benchmarks from upstream

This commit is contained in:
Péter Szilágyi 2021-01-11 10:31:03 +02:00
parent 6b88ab75bc
commit ab5e3f400f
No known key found for this signature in database
GPG Key ID: E9AE538CEDF8293D
2 changed files with 230 additions and 0 deletions

130
common/prque/prque_test.go Normal file

@ -0,0 +1,130 @@
// CookieJar - A contestant's algorithm toolbox
// Copyright (c) 2013 Peter Szilagyi. All rights reserved.
//
// CookieJar is dual licensed: use of this source code is governed by a BSD
// license that can be found in the LICENSE file. Alternatively, the CookieJar
// toolbox may be used in accordance with the terms and conditions contained
// in a signed written agreement between you and the author(s).
package prque
import (
"math/rand"
"testing"
)
func TestPrque(t *testing.T) {
// Generate a batch of random data and a specific priority order
size := 16 * blockSize
prio := rand.Perm(size)
data := make([]int, size)
for i := 0; i < size; i++ {
data[i] = rand.Int()
}
queue := New(nil)
for rep := 0; rep < 2; rep++ {
// Fill a priority queue with the above data
for i := 0; i < size; i++ {
queue.Push(data[i], int64(prio[i]))
if queue.Size() != i+1 {
t.Errorf("queue size mismatch: have %v, want %v.", queue.Size(), i+1)
}
}
// Create a map the values to the priorities for easier verification
dict := make(map[int64]int)
for i := 0; i < size; i++ {
dict[int64(prio[i])] = data[i]
}
// Pop out the elements in priority order and verify them
prevPrio := int64(size + 1)
for !queue.Empty() {
val, prio := queue.Pop()
if prio > prevPrio {
t.Errorf("invalid priority order: %v after %v.", prio, prevPrio)
}
prevPrio = prio
if val != dict[prio] {
t.Errorf("push/pop mismatch: have %v, want %v.", val, dict[prio])
}
delete(dict, prio)
}
}
}
func TestReset(t *testing.T) {
// Generate a batch of random data and a specific priority order
size := 16 * blockSize
prio := rand.Perm(size)
data := make([]int, size)
for i := 0; i < size; i++ {
data[i] = rand.Int()
}
queue := New(nil)
for rep := 0; rep < 2; rep++ {
// Fill a priority queue with the above data
for i := 0; i < size; i++ {
queue.Push(data[i], int64(prio[i]))
if queue.Size() != i+1 {
t.Errorf("queue size mismatch: have %v, want %v.", queue.Size(), i+1)
}
}
// Create a map the values to the priorities for easier verification
dict := make(map[int64]int)
for i := 0; i < size; i++ {
dict[int64(prio[i])] = data[i]
}
// Pop out half the elements in priority order and verify them
prevPrio := int64(size + 1)
for i := 0; i < size/2; i++ {
val, prio := queue.Pop()
if prio > prevPrio {
t.Errorf("invalid priority order: %v after %v.", prio, prevPrio)
}
prevPrio = prio
if val != dict[prio] {
t.Errorf("push/pop mismatch: have %v, want %v.", val, dict[prio])
}
delete(dict, prio)
}
// Reset and ensure it's empty
queue.Reset()
if !queue.Empty() {
t.Errorf("priority queue not empty after reset: %v", queue)
}
}
}
func BenchmarkPush(b *testing.B) {
// Create some initial data
data := make([]int, b.N)
prio := make([]int64, b.N)
for i := 0; i < len(data); i++ {
data[i] = rand.Int()
prio[i] = rand.Int63()
}
// Execute the benchmark
b.ResetTimer()
queue := New(nil)
for i := 0; i < len(data); i++ {
queue.Push(data[i], prio[i])
}
}
func BenchmarkPop(b *testing.B) {
// Create some initial data
data := make([]int, b.N)
prio := make([]int64, b.N)
for i := 0; i < len(data); i++ {
data[i] = rand.Int()
prio[i] = rand.Int63()
}
queue := New(nil)
for i := 0; i < len(data); i++ {
queue.Push(data[i], prio[i])
}
// Execute the benchmark
b.ResetTimer()
for !queue.Empty() {
queue.Pop()
}
}

100
common/prque/sstack_test.go Normal file

@ -0,0 +1,100 @@
// CookieJar - A contestant's algorithm toolbox
// Copyright (c) 2013 Peter Szilagyi. All rights reserved.
//
// CookieJar is dual licensed: use of this source code is governed by a BSD
// license that can be found in the LICENSE file. Alternatively, the CookieJar
// toolbox may be used in accordance with the terms and conditions contained
// in a signed written agreement between you and the author(s).
package prque
import (
"math/rand"
"sort"
"testing"
)
func TestSstack(t *testing.T) {
// Create some initial data
size := 16 * blockSize
data := make([]*item, size)
for i := 0; i < size; i++ {
data[i] = &item{rand.Int(), rand.Int63()}
}
stack := newSstack(nil)
for rep := 0; rep < 2; rep++ {
// Push all the data into the stack, pop out every second
secs := []*item{}
for i := 0; i < size; i++ {
stack.Push(data[i])
if i%2 == 0 {
secs = append(secs, stack.Pop().(*item))
}
}
rest := []*item{}
for stack.Len() > 0 {
rest = append(rest, stack.Pop().(*item))
}
// Make sure the contents of the resulting slices are ok
for i := 0; i < size; i++ {
if i%2 == 0 && data[i] != secs[i/2] {
t.Errorf("push/pop mismatch: have %v, want %v.", secs[i/2], data[i])
}
if i%2 == 1 && data[i] != rest[len(rest)-i/2-1] {
t.Errorf("push/pop mismatch: have %v, want %v.", rest[len(rest)-i/2-1], data[i])
}
}
}
}
func TestSstackSort(t *testing.T) {
// Create some initial data
size := 16 * blockSize
data := make([]*item, size)
for i := 0; i < size; i++ {
data[i] = &item{rand.Int(), int64(i)}
}
// Push all the data into the stack
stack := newSstack(nil)
for _, val := range data {
stack.Push(val)
}
// Sort and pop the stack contents (should reverse the order)
sort.Sort(stack)
for _, val := range data {
out := stack.Pop()
if out != val {
t.Errorf("push/pop mismatch after sort: have %v, want %v.", out, val)
}
}
}
func TestSstackReset(t *testing.T) {
// Create some initial data
size := 16 * blockSize
data := make([]*item, size)
for i := 0; i < size; i++ {
data[i] = &item{rand.Int(), rand.Int63()}
}
stack := newSstack(nil)
for rep := 0; rep < 2; rep++ {
// Push all the data into the stack, pop out every second
secs := []*item{}
for i := 0; i < size; i++ {
stack.Push(data[i])
if i%2 == 0 {
secs = append(secs, stack.Pop().(*item))
}
}
// Reset and verify both pulled and stack contents
stack.Reset()
if stack.Len() != 0 {
t.Errorf("stack not empty after reset: %v", stack)
}
for i := 0; i < size; i++ {
if i%2 == 0 && data[i] != secs[i/2] {
t.Errorf("push/pop mismatch: have %v, want %v.", secs[i/2], data[i])
}
}
}
}