av/ringbuffer/RingBuffer_test.go

351 lines
8.0 KiB
Go

/*
NAME
RingBuffer_test.go - a test suite adopting the golang testing library to test functionality of the
RingBuffer structure
DESCRIPTION
See Readme.md
AUTHOR
Saxon Nelson-Milton <saxon.milton@gmail.com>
LICENSE
RingBuffer_test.go is Copyright (C) 2017 the Australian Ocean Lab (AusOcean)
It is free software: you can redistribute it and/or modify them
under the terms of the GNU General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
It is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with revid in gpl.txt. If not, see [GNU licenses](http://www.gnu.org/licenses).
*/
package ringbuffer
import (
"testing"
"time"
)
const (
testBufferSize = 10
testElementSize = 1
testOverFlowSize = 5
testDataSize = 1
testConcurrencyBufferSize = 1000
)
var rb *ringBuffer
// Call when we get an error we shouldn't have
func falseErrorFail(t *testing.T, err error) {
t.Errorf("Should not have got error: %v", err)
}
// Call when we should have got an error but didnt
func noErrorFail(t *testing.T) {
t.Errorf("Should have got error!")
}
// Test that the Make method correctly allocates memory for arbitrary buffer
// size of 10 and arbitrary element size of 10
func TestMake(t *testing.T) {
rb = NewRingBuffer(testBufferSize, testElementSize)
if len(rb.dataMemory) != testBufferSize {
t.Errorf("Len of buffer is wrong!")
}
if len(rb.dataMemory[0]) != testElementSize {
t.Errorf("Len of individual element is wrong!")
}
}
// Test call to done writing when no writing has occured.
// We pass arbitrary clipSize.
func TestDoneWriting1(t *testing.T) {
if rb.DoneWriting(testDataSize) == nil {
noErrorFail(t)
}
}
// Test call to done writing when there has been some 'writing'
func TestDoneWriting2(t *testing.T) {
if _, err := rb.Get(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneWriting(testDataSize); err != nil {
falseErrorFail(t, err)
}
}
// Test call to done reading when there hasn't been any reading
func TestDoneReading1(t *testing.T) {
rb = NewRingBuffer(testBufferSize, testElementSize)
if rb.DoneReading() == nil {
noErrorFail(t)
}
}
// Test read when there hasn't been anything written to buffer
func TestReadingWithoutWrite(t *testing.T) {
rb = NewRingBuffer(testBufferSize, testElementSize)
_, err := rb.Read()
if err == nil {
noErrorFail(t)
}
}
// Try Writing twice without calling DoneWriting
func TestWritingTwice(t *testing.T) {
rb = NewRingBuffer(testBufferSize, testElementSize)
_, err := rb.Get()
_, err = rb.Get()
if err == nil {
noErrorFail(t)
}
}
// Test call to done reading when there has been some reading
func TestDoneReading2(t *testing.T) {
rb = NewRingBuffer(testBufferSize, testElementSize)
_, err := rb.Get()
rb.DoneWriting(testDataSize)
_, err = rb.Read()
if err != nil {
falseErrorFail(t, err)
}
rb.DoneReading()
}
// Testing writing then reading for single 'write' and single 'read' routines
func TestWritingAndReading1(t *testing.T) {
rb = NewRingBuffer(testBufferSize, testElementSize)
if _, err := rb.Get(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneWriting(testDataSize); err != nil {
falseErrorFail(t, err)
}
if _, err := rb.Read(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneReading(); err != nil {
falseErrorFail(t, err)
}
}
// Testing two 'writes' and two 'reads'
func TestWritingAndReading2(t *testing.T) {
rb = NewRingBuffer(testBufferSize, testElementSize)
for i := 0; i < 2; i++ {
if _, err := rb.Get(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneWriting(testDataSize); err != nil {
falseErrorFail(t, err)
}
}
for i := 0; i < 2; i++ {
if _, err := rb.Read(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneReading(); err != nil {
falseErrorFail(t, err)
}
}
}
// Testing one 'write' and two 'reads'
func TestWritingAndReading3(t *testing.T) {
rb = NewRingBuffer(testBufferSize, testElementSize)
if _, err := rb.Get(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneWriting(testDataSize); err != nil {
falseErrorFail(t, err)
}
var err1 error
var err2 error
for i := 0; i < 2; i++ {
_, err1 = rb.Read()
err2 = rb.DoneReading()
}
if err1 == nil {
noErrorFail(t)
}
if err2 == nil {
noErrorFail(t)
}
}
// Test two 'writes' and one 'read'
func TestWritingAndReading4(t *testing.T) {
rb = NewRingBuffer(testBufferSize, testElementSize)
for i := 0; i < 2; i++ {
if _, err := rb.Get(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneWriting(testDataSize); err != nil {
falseErrorFail(t, err)
}
}
if _, err := rb.Read(); err != nil {
falseErrorFail(t, err)
}
if err := rb.DoneReading(); err != nil {
falseErrorFail(t, err)
}
}
// Test writing past capacity
func TestWritingAndReading5(t *testing.T) {
rb = NewRingBuffer(testOverFlowSize, testElementSize)
var err1 error
var err2 error
for i := 0; i < testOverFlowSize+1; i++ {
_, err1 = rb.Get()
err2 = rb.DoneWriting(testDataSize)
}
if err1 == nil {
noErrorFail(t)
}
if err2 == nil {
noErrorFail(t)
}
}
// Test writing to size, then read some, then 'write' to test that we go back
// to start of buffer
func TestWritingAndReading6(t *testing.T) {
rb = NewRingBuffer(testOverFlowSize, testElementSize)
var err1 error
var err2 error
for i := 0; i < testOverFlowSize; i++ {
_, err1 = rb.Get()
err2 = rb.DoneWriting(testDataSize)
}
if err1 != nil {
falseErrorFail(t, err1)
}
if err2 != nil {
falseErrorFail(t, err2)
}
for i := 0; i < 2; i++ {
_, err1 = rb.Read()
err2 = rb.DoneReading()
}
if err1 != nil {
falseErrorFail(t, err1)
}
if err2 != nil {
falseErrorFail(t, err2)
}
_, err1 = rb.Get()
err2 = rb.DoneWriting(testDataSize)
if err1 != nil {
falseErrorFail(t, err1)
}
if err2 != nil {
falseErrorFail(t, err2)
}
}
// Now let's do the previous test again, but this time we will try to write
// past capacity
func TestWritingAndReading7(t *testing.T) {
rb = NewRingBuffer(testOverFlowSize, testElementSize)
var err1 error
var err2 error
for i := 0; i < testOverFlowSize; i++ {
_, err1 = rb.Get()
err2 = rb.DoneWriting(testDataSize)
}
if err1 != nil {
falseErrorFail(t, err1)
}
if err2 != nil {
falseErrorFail(t, err2)
}
for i := 0; i < 2; i++ {
_, err1 = rb.Read()
err2 = rb.DoneReading()
}
if err1 != nil {
falseErrorFail(t, err1)
}
if err2 != nil {
falseErrorFail(t, err2)
}
for i := 0; i < testOverFlowSize; i++ {
_, err1 = rb.Get()
err2 = rb.DoneWriting(testDataSize)
}
if err1 == nil {
noErrorFail(t)
}
if err2 == nil {
noErrorFail(t)
}
}
// Test reading twice without call to DoneReading
func TestWritingAndReading8(t *testing.T) {
rb = NewRingBuffer(testBufferSize, 10)
var err1 error
var err2 error
for i := 0; i < 2; i++ {
_, err1 = rb.Get()
err2 = rb.DoneWriting(testDataSize)
}
if err1 != nil {
falseErrorFail(t, err1)
}
if err2 != nil {
falseErrorFail(t, err2)
}
for i := 0; i < 2; i++ {
_, err1 = rb.Read()
}
if err1 == nil {
noErrorFail(t)
}
}
// Let's see if we can do concurrency. (tip: run as: go test -race) to see
// any data race issues. We will continously write and read at concurrently
// time for a second
func TestConcurrency1(t *testing.T) {
rb = NewRingBuffer(testConcurrencyBufferSize, testElementSize)
go func() {
for i := 0; i < 100; i++ {
if data, err1 := rb.Read(); data != nil {
err2 := rb.DoneReading()
if err1 != nil {
falseErrorFail(t, err1)
}
if err2 != nil {
falseErrorFail(t, err2)
}
}
}
}()
go func() {
for i := 0; i < 100; i++ {
_, err1 := rb.Get()
err2 := rb.DoneWriting(testDataSize)
if err1 != nil {
falseErrorFail(t, err1)
}
if err2 != nil {
falseErrorFail(t, err2)
}
}
}()
time.Sleep(1000 * time.Millisecond)
}