deque-int/deque_test.go
2018-04-23 23:06:09 -04:00

508 lines
9.1 KiB
Go

package deque
import "testing"
func TestEmpty(t *testing.T) {
var q Deque
if q.Len() != 0 {
t.Error("q.Len() =", q.Len(), "expect 0")
}
}
func TestFrontBack(t *testing.T) {
var q Deque
q.PushBack("foo")
q.PushBack("bar")
q.PushBack("baz")
if q.Front() != "foo" {
t.Error("wrong value at front of queue")
}
if q.Back() != "baz" {
t.Error("wrong value at back of queue")
}
if q.PopFront() != "foo" {
t.Error("wrong value removed from front of queue")
}
if q.Front() != "bar" {
t.Error("wrong value remaining at front of queue")
}
if q.Back() != "baz" {
t.Error("wrong value remaining at back of queue")
}
if q.PopBack() != "baz" {
t.Error("wrong value removed from back of queue")
}
if q.Front() != "bar" {
t.Error("wrong value remaining at front of queue")
}
if q.Back() != "bar" {
t.Error("wrong value remaining at back of queue")
}
}
func TestGrowShrink(t *testing.T) {
var q Deque
for i := 0; i < minCapacity*2; i++ {
if q.Len() != i {
t.Error("q.Len() =", q.Len(), "expected", i)
}
q.PushBack(i)
}
// Check that all values are as expected.
for i := 0; i < minCapacity*2; i++ {
if q.PeekAt(i) != i {
t.Errorf("q.PeekAt(%d) = %d, expected %d", i, q.PeekAt(i), i)
}
}
bufLen := len(q.buf)
// Remove from back.
for i := minCapacity * 2; i > 0; i-- {
if q.Len() != i {
t.Error("q.Len() =", q.Len(), "expected", i)
}
x := q.PopBack()
if x != i-1 {
t.Error("q.PopBack() =", x, "expected", i-1)
}
}
if q.Len() != 0 {
t.Error("q.Len() =", q.Len(), "expected 0")
}
if len(q.buf) == bufLen {
t.Error("queue buffer did not shrink")
}
// Fill up queue again.
for i := 0; i < minCapacity*2; i++ {
if q.Len() != i {
t.Error("q.Len() =", q.Len(), "expected", i)
}
q.PushBack(i)
}
bufLen = len(q.buf)
// Remove from Front
for i := 0; i < minCapacity*2; i++ {
if q.Len() != minCapacity*2-i {
t.Error("q.Len() =", q.Len(), "expected", minCapacity*2-i)
}
x := q.PopFront()
if x != i {
t.Error("q.PopBack() =", x, "expected", i)
}
}
if q.Len() != 0 {
t.Error("q.Len() =", q.Len(), "expected 0")
}
if len(q.buf) == bufLen {
t.Error("queue buffer did not shrink")
}
}
func TestDequeSimple(t *testing.T) {
q := new(Deque)
for i := 0; i < minCapacity; i++ {
q.PushBack(i)
}
for i := 0; i < minCapacity; i++ {
if q.Front() != i {
t.Error("peek", i, "had value", q.Front())
}
x := q.PopFront()
if x != i {
t.Error("remove", i, "had value", x)
}
}
q.Clear()
for i := 0; i < minCapacity; i++ {
q.PushFront(i)
}
for i := minCapacity - 1; i >= 0; i-- {
x := q.PopFront()
if x != i {
t.Error("remove", i, "had value", x)
}
}
}
func TestDequeWrap(t *testing.T) {
q := new(Deque)
for i := 0; i < minCapacity; i++ {
q.PushBack(i)
}
for i := 0; i < 3; i++ {
q.PopFront()
q.PushBack(minCapacity + i)
}
for i := 0; i < minCapacity; i++ {
if q.Front().(int) != i+3 {
t.Error("peek", i, "had value", q.Front())
}
q.PopFront()
}
}
func TestDequeWrapReverse(t *testing.T) {
q := new(Deque)
for i := 0; i < minCapacity; i++ {
q.PushFront(i)
}
for i := 0; i < 3; i++ {
q.PopBack()
q.PushFront(minCapacity + i)
}
for i := 0; i < minCapacity; i++ {
if q.Back().(int) != i+3 {
t.Error("peek", i, "had value", q.Front())
}
q.PopBack()
}
}
func TestDequeLen(t *testing.T) {
q := new(Deque)
if q.Len() != 0 {
t.Error("empty queue length not 0")
}
for i := 0; i < 1000; i++ {
q.PushBack(i)
if q.Len() != i+1 {
t.Error("adding: queue with", i, "elements has length", q.Len())
}
}
for i := 0; i < 1000; i++ {
q.PopFront()
if q.Len() != 1000-i-1 {
t.Error("removing: queue with", 1000-i-i, "elements has length", q.Len())
}
}
}
func TestDequePeekAt(t *testing.T) {
q := new(Deque)
for i := 0; i < 1000; i++ {
q.PushBack(i)
for j := 0; j < q.Len(); j++ {
if q.PeekAt(j).(int) != j {
t.Errorf("index %d doesn't contain %d", j, j)
}
}
}
}
func TestDequePeekAtNegative(t *testing.T) {
q := new(Deque)
for i := 0; i < 1000; i++ {
q.PushBack(i)
for j := 1; j <= q.Len(); j++ {
if q.PeekAt(-j).(int) != q.Len()-j {
t.Errorf("index %d doesn't contain %d", -j, q.Len()-j)
}
}
}
}
func TestDequeBack(t *testing.T) {
q := new(Deque)
for i := 0; i < minCapacity+5; i++ {
q.PushBack(i)
if q.Back() != i {
t.Errorf("Back returned wrong value")
}
}
}
func TestCopy(t *testing.T) {
q := new(Deque)
a := make([]interface{}, minCapacity)
if q.Copy(a) != 0 {
t.Error("Copied wrong size, expected 0")
}
for i := 0; i < minCapacity/2; i++ {
q.PushBack(i)
q.PopFront()
}
for i := 0; i < minCapacity; i++ {
q.PushBack(i)
}
q.Copy(a)
for i := range a {
if a[i].(int) != i {
t.Error("Copy has wrong value at position", i)
}
}
a = []interface{}{}
if q.Copy(a) != 0 {
t.Error("Copied wrong size, expected 0")
}
a = make([]interface{}, q.Len()/2)
if q.Copy(a) != len(a) {
t.Error("Copied wrong size, expected", len(a))
}
a = make([]interface{}, q.Len()*2)
if q.Copy(a) != q.Len() {
t.Error("Copied wrong size", q.Len())
}
}
func TestRotate(t *testing.T) {
q := new(Deque)
for i := 0; i < 10; i++ {
q.PushBack(i)
}
a := make([]interface{}, q.Len())
for i := 0; i < q.Len(); i++ {
q.Copy(a)
x := i
for n := range a {
if a[n] != x {
t.Fatalf("a[%d] != %d after rotate and copy", n, x)
}
x++
if x == q.Len() {
x = 0
}
}
v := q.PopFront()
if v.(int) != i {
t.Fatal("wrong value during rotation")
}
q.PushBack(v)
}
for i := q.Len() - 1; i >= 0; i-- {
v := q.PopBack()
if v.(int) != i {
t.Fatal("wrong value during reverse rotation")
}
q.PushFront(v)
}
}
func TestDequeClear(t *testing.T) {
q := new(Deque)
for i := 0; i < 100; i++ {
q.PushBack(i)
}
if q.Len() != 100 {
t.Error("push: queue with 100 elements has length", q.Len())
}
cap := len(q.buf)
q.Clear()
if q.Len() != 0 {
t.Error("empty queue length not 0 after clear")
}
if len(q.buf) != cap {
t.Error("queue capacity changed after clear")
}
// Check that there are no remaining references after Clear()
for i := 0; i < len(q.buf); i++ {
if q.buf[i] != nil {
t.Error("queue has non-nil deleted elements after Clear()")
break
}
}
}
func TestPeekAtOutOfRangePanics(t *testing.T) {
q := new(Deque)
q.PushBack(1)
q.PushBack(2)
q.PushBack(3)
assertPanics(t, "should panic when negative index", func() {
q.PeekAt(-4)
})
assertPanics(t, "should panic when index greater than length", func() {
q.PeekAt(4)
})
}
func TestFrontBackOutOfRangePanics(t *testing.T) {
const msg = "should panic when peeking empty queue"
q := new(Deque)
assertPanics(t, msg, func() {
q.Front()
})
assertPanics(t, msg, func() {
q.Back()
})
q.PushBack(1)
q.PopFront()
assertPanics(t, msg, func() {
q.Front()
})
assertPanics(t, msg, func() {
q.Back()
})
}
func TestPopFrontOutOfRangePanics(t *testing.T) {
q := new(Deque)
assertPanics(t, "should panic when removing empty queue", func() {
q.PopFront()
})
q.PushBack(1)
q.PopFront()
assertPanics(t, "should panic when removing emptied queue", func() {
q.PopFront()
})
}
func TestPopBackOutOfRangePanics(t *testing.T) {
q := new(Deque)
assertPanics(t, "should panic when removing empty queue", func() {
q.PopBack()
})
q.PushBack(1)
q.PopBack()
assertPanics(t, "should panic when removing emptied queue", func() {
q.PopBack()
})
}
func assertPanics(t *testing.T, name string, f func()) {
defer func() {
if r := recover(); r == nil {
t.Errorf("%s: didn't panic as expected", name)
}
}()
f()
}
// Size (number of items) of Deque to use for benchmarks.
const size = minCapacity + (minCapacity / 2)
func BenchmarkPushFront(b *testing.B) {
var q Deque
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
q.PushFront(n)
}
}
}
func BenchmarkPushBack(b *testing.B) {
var q Deque
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
q.PushBack(n)
}
}
}
func BenchmarkSerial(b *testing.B) {
var q Deque
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
q.PushBack(i)
}
for n := 0; n < size; n++ {
x := q.Front()
if q.PopFront() != x {
panic("bad PopFront()")
}
}
}
}
func BenchmarkSerialReverse(b *testing.B) {
var q Deque
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
q.PushFront(i)
}
for n := 0; n < size; n++ {
x := q.Back()
if q.PopBack() != x {
panic("bad PopBack()")
}
}
}
}
func BenchmarkRotate(b *testing.B) {
q := new(Deque)
for i := 0; i < size; i++ {
q.PushBack(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for j := 0; j < size; j++ {
v := q.PopFront()
q.PushBack(v)
}
}
}
func BenchmarkRotateReverse(b *testing.B) {
q := new(Deque)
for i := 0; i < size; i++ {
q.PushBack(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for j := 0; j < size; j++ {
v := q.PopBack()
q.PushFront(v)
}
}
}
func BenchmarkDequePeekAt(b *testing.B) {
q := new(Deque)
for i := 0; i < size; i++ {
q.PushBack(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
for j := 0; j < size; j++ {
q.PeekAt(j)
}
}
}
func BenchmarkDequePushPop(b *testing.B) {
q := new(Deque)
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
q.PushBack(nil)
q.PopFront()
}
}
}