/* 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 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" ) // 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!") } // RingBuffer object used over testing funcs var ringBuffer = RingBuffer{} // 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) { ringBuffer.Make(10, 10) if len(ringBuffer.Memory) != 10 { t.Errorf("Len of buffer is wrong!") } if len(ringBuffer.Memory[0]) != 10 { 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 ringBuffer.DoneWriting(1) == nil { noErrorFail(t) } } // Test call to done writing when there has been some 'writing' func TestDoneWriting2(t *testing.T) { if _, err := ringBuffer.Get(); err != nil { falseErrorFail(t, err) } if err := ringBuffer.DoneWriting(1); err != nil { falseErrorFail(t, err) } } // Try to 'write' to the buffer when full. Set buffer size to arbitrary number of 3. // We write over buffer size of 3 (write 4 times) func TestWritingWhenFull(t *testing.T) { ringBuffer.Make(3, 10) var err error for i := 0; i < 4; i++ { _, err = ringBuffer.Get() ringBuffer.DoneWriting(1) } if err == nil { noErrorFail(t) } } // Test call to done reading when there hasn't been any reading func TestDoneReading1(t *testing.T) { ringBuffer.Make(10, 10) if ringBuffer.DoneReading() == nil { noErrorFail(t) } } // Test read when there hasn't been anything written to buffer func TestReadingWithoutWrite(t *testing.T) { ringBuffer.Make(10, 10) _, _, err := ringBuffer.Read() if err == nil { noErrorFail(t) } } // Try Writing twice without calling DoneWriting func TestWritingTwice(t *testing.T) { ringBuffer.Make(10, 10) _, err := ringBuffer.Get() _, err = ringBuffer.Get() if err == nil { noErrorFail(t) } } // Test call to done reading when there has been some reading func TestDoneReading2(t *testing.T) { ringBuffer.Make(10, 10) _, err := ringBuffer.Get() ringBuffer.DoneWriting(1) _, _, err = ringBuffer.Read() if err != nil { falseErrorFail(t, err) } ringBuffer.DoneReading() } // Testing writing then reading for single 'write' and single 'read' routines func TestWritingAndReading1(t *testing.T) { ringBuffer.Make(10, 10) if _, err := ringBuffer.Get(); err != nil { falseErrorFail(t, err) } if err := ringBuffer.DoneWriting(1); err != nil { falseErrorFail(t, err) } if _, _, err := ringBuffer.Read(); err != nil { falseErrorFail(t, err) } if err := ringBuffer.DoneReading(); err != nil { falseErrorFail(t, err) } } // Testing two 'writes' and two 'reads' func TestWritingAndReading2(t *testing.T) { ringBuffer.Make(10, 10) for i := 0; i < 2; i++ { if _, err := ringBuffer.Get(); err != nil { falseErrorFail(t, err) } if err := ringBuffer.DoneWriting(1); err != nil { falseErrorFail(t, err) } } for i := 0; i < 2; i++ { if _, _, err := ringBuffer.Read(); err != nil { falseErrorFail(t, err) } if err := ringBuffer.DoneReading(); err != nil { falseErrorFail(t, err) } } } // Testing one 'write' and two 'reads' func TestWritingAndReading3(t *testing.T) { ringBuffer.Make(10, 10) if _, err := ringBuffer.Get(); err != nil { falseErrorFail(t, err) } if err := ringBuffer.DoneWriting(1); err != nil { falseErrorFail(t, err) } var err1 error var err2 error for i := 0; i < 2; i++ { _, _, err1 = ringBuffer.Read() err2 = ringBuffer.DoneReading() } if err1 == nil { noErrorFail(t) } if err2 == nil { noErrorFail(t) } } // Test two 'writes' and one 'read' func TestWritingAndReading4(t *testing.T) { ringBuffer.Make(10, 10) for i := 0; i < 2; i++ { if _, err := ringBuffer.Get(); err != nil { falseErrorFail(t, err) } if err := ringBuffer.DoneWriting(1); err != nil { falseErrorFail(t, err) } } if _, _, err := ringBuffer.Read(); err != nil { falseErrorFail(t, err) } if err := ringBuffer.DoneReading(); err != nil { falseErrorFail(t, err) } } // Test writing past capacity func TestWritingAndReading5(t *testing.T) { ringBuffer.Make(4, 10) var err1 error var err2 error for i := 0; i < 5; i++ { _, err1 = ringBuffer.Get() err2 = ringBuffer.DoneWriting(1) } 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) { ringBuffer.Make(4, 10) var err1 error var err2 error for i := 0; i < 4; i++ { _, err1 = ringBuffer.Get() err2 = ringBuffer.DoneWriting(1) } if err1 != nil { falseErrorFail(t, err1) } if err2 != nil { falseErrorFail(t, err2) } for i := 0; i < 2; i++ { _, _, err1 = ringBuffer.Read() err2 = ringBuffer.DoneReading() } if err1 != nil { falseErrorFail(t, err1) } if err2 != nil { falseErrorFail(t, err2) } _, err1 = ringBuffer.Get() err2 = ringBuffer.DoneWriting(1) 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) { ringBuffer.Make(4, 10) var err1 error var err2 error for i := 0; i < 4; i++ { _, err1 = ringBuffer.Get() err2 = ringBuffer.DoneWriting(1) } if err1 != nil { falseErrorFail(t, err1) } if err2 != nil { falseErrorFail(t, err2) } for i := 0; i < 2; i++ { _, _, err1 = ringBuffer.Read() err2 = ringBuffer.DoneReading() } if err1 != nil { falseErrorFail(t, err1) } if err2 != nil { falseErrorFail(t, err2) } for i := 0; i < 3; i++ { _, err1 = ringBuffer.Get() err2 = ringBuffer.DoneWriting(1) } if err1 == nil { noErrorFail(t) } if err2 == nil { noErrorFail(t) } } // Test reading twice without call to DoneReading func TestWritingAndReading8(t *testing.T) { ringBuffer.Make(4, 10) var err1 error var err2 error for i := 0; i < 4; i++ { _, err1 = ringBuffer.Get() err2 = ringBuffer.DoneWriting(1) } if err1 != nil { falseErrorFail(t, err1) } if err2 != nil { falseErrorFail(t, err2) } for i := 0; i < 2; i++ { _, _, err1 = ringBuffer.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) { ringBuffer.Make(1000, 10) go func() { for i := 0; i < 100; i++ { if data, _, err1 := ringBuffer.Read(); data != nil { err2 := ringBuffer.DoneReading() if err1 != nil { falseErrorFail(t, err1) } if err2 != nil { falseErrorFail(t, err2) } } } }() go func() { for i := 0; i < 100; i++ { _, err1 := ringBuffer.Get() err2 := ringBuffer.DoneWriting(1) if err1 != nil { falseErrorFail(t, err1) } if err2 != nil { falseErrorFail(t, err2) } } }() time.Sleep(1000 * time.Millisecond) }