The existing DocumentBuffer interface provided no facility to iterate over events in order without caching them all in memory and pushing/popping them. This was deemed significantly unoptimal and so Apply() was born. When Apply() is called, DocumentBuffer will recieve a filter callable (functor, lambda, or closure) and will call it on all documents in order throughout the entire cache and store, without caching stored events or modifying the cache either. The filter Apply() uses will recieve one document and return true or false: true to continue iterating and false to stop iterating. Signed-off-by: Ava Affine <ava@sunnypup.io>
337 lines
8.3 KiB
Go
337 lines
8.3 KiB
Go
package docbuf
|
|
|
|
import (
|
|
"testing"
|
|
"fmt"
|
|
)
|
|
|
|
func docu(ctr *int) string {
|
|
// we add a new line to try to trick the docbuf
|
|
// into thinking there is an extra doc here.
|
|
// but there isnt one.
|
|
s := fmt.Sprintf("%d\n", *ctr)
|
|
(*ctr) += 1
|
|
|
|
return s
|
|
}
|
|
|
|
func TestPushPop(t *testing.T) {
|
|
docCtr := 1
|
|
|
|
backingStore := NewReadWriteSeekString()
|
|
buf, e := NewDocumentBuffer(3, &backingStore)
|
|
if e != nil {
|
|
t.Fatalf("error making documentbuffer: %e", e)
|
|
}
|
|
|
|
// does push add 1 to cache
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 1 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
|
|
// does push past cache demote first document
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 2 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 3 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil || backingStore.Cursor() == 0 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
|
|
if backingStore.Contents() != "MQo=" {
|
|
t.Fatalf("expected oldest doc to be in store, got %s",
|
|
backingStore.Contents())
|
|
}
|
|
|
|
// does pop promote document from cache
|
|
doc, err := buf.Pop()
|
|
if err != nil || doc != "4\n" {
|
|
t.Fatalf("did not get expected doc from cache: %s (%e)", doc, err)
|
|
}
|
|
if buf.Cached() != 3 {
|
|
t.Fatalf("doc buffer did not promote: %d", buf.Cached())
|
|
}
|
|
|
|
// does pop past empty throw the right error
|
|
doc, err = buf.Pop()
|
|
if err != nil || doc != "3\n" {
|
|
t.Fatalf("did not get expected doc from cache: %s (%e)", doc, err)
|
|
}
|
|
doc, err = buf.Pop()
|
|
if err != nil || doc != "2\n" {
|
|
t.Fatalf("did not get expected doc from cache: %s (%e)", doc, err)
|
|
}
|
|
doc, err = buf.Pop()
|
|
if err != nil || doc != "1\n" {
|
|
t.Logf("bs: %s", backingStore.Contents())
|
|
t.Fatalf("did not get expected doc from cache: %s (%e)", doc, err)
|
|
}
|
|
doc, err = buf.Pop()
|
|
if err == nil ||
|
|
doc != "" ||
|
|
err.Error() != "Can't pop from empty buffer" {
|
|
t.Fatalf("did not get expected doc from cache: %s", doc)
|
|
}
|
|
}
|
|
|
|
func TestRemove(t *testing.T) {
|
|
docCtr := 1
|
|
backingStore := NewReadWriteSeekString()
|
|
buf, e := NewDocumentBuffer(3, &backingStore)
|
|
if e != nil {
|
|
t.Fatalf("error making documentbuffer: %e", e)
|
|
}
|
|
|
|
// setup test data
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 1 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 2 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 3 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil ||
|
|
buf.Cached() != 3 || backingStore.Contents() != "MQo=" {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
|
|
// tests
|
|
docs, err := buf.Remove(2)
|
|
if err != nil ||
|
|
len(docs) != 2 ||
|
|
docs[0] != "4\n" ||
|
|
docs[1] != "3\n" ||
|
|
buf.Cached() != 2 {
|
|
t.Fatalf("error removing: %e", err)
|
|
}
|
|
|
|
for range 5 {
|
|
if err := buf.Push(docu(&docCtr)); err != nil {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
}
|
|
|
|
docs, err = buf.Remove(4)
|
|
if err != nil ||
|
|
len(docs) != 4 ||
|
|
docs[0] != "9\n" ||
|
|
docs[1] != "8\n" ||
|
|
docs[2] != "7\n" ||
|
|
docs[3] != "6\n" ||
|
|
buf.Cached() != 3 {
|
|
t.Fatalf("error removing: %e", err)
|
|
}
|
|
|
|
docs, err = buf.Remove(3)
|
|
if err != nil ||
|
|
len(docs) != 3 ||
|
|
docs[0] != "5\n" ||
|
|
docs[1] != "2\n" ||
|
|
docs[2] != "1\n" ||
|
|
buf.Cached() != 0 {
|
|
t.Fatalf("error removing: %e", err)
|
|
}
|
|
}
|
|
|
|
func TestFlush(t *testing.T) {
|
|
docCtr := 1
|
|
expectedDoc := "MQo=\nMgo=\nMwo=\nNAo="
|
|
backingStore := NewReadWriteSeekString()
|
|
buf, e := NewDocumentBuffer(3, &backingStore)
|
|
if e != nil {
|
|
t.Fatalf("error making documentbuffer: %e", e)
|
|
}
|
|
|
|
// setup test data
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 1 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 2 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 3 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil ||
|
|
buf.Cached() != 3 || backingStore.Contents() == "Nao=\n" {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
|
|
// test
|
|
if err := buf.Flush(); err != nil {
|
|
t.Fatalf("error flushing buffer: %e", err)
|
|
}
|
|
|
|
if backingStore.Contents() != expectedDoc {
|
|
t.Fatalf("did not get expected document: %s", backingStore.Contents())
|
|
}
|
|
}
|
|
|
|
func TestPeek(t *testing.T) {
|
|
docCtr := 1
|
|
backingStore := NewReadWriteSeekString()
|
|
buf, e := NewDocumentBuffer(3, &backingStore)
|
|
if e != nil {
|
|
t.Fatalf("error making documentbuffer: %e", e)
|
|
}
|
|
|
|
// setup test data
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 1 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
|
|
// test
|
|
if d, e := buf.Peek(); e != nil ||
|
|
d != "1\n" ||
|
|
buf.Cached() != 1 {
|
|
t.Fatalf("error peeking: %e", e)
|
|
}
|
|
}
|
|
|
|
func TestRead(t *testing.T) {
|
|
docCtr := 1
|
|
backingStore := NewReadWriteSeekString()
|
|
buf, e := NewDocumentBuffer(3, &backingStore)
|
|
if e != nil {
|
|
t.Fatalf("error making documentbuffer: %e", e)
|
|
}
|
|
|
|
// setup test data
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 1 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 2 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 3 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil ||
|
|
buf.Cached() != 3 || backingStore.Contents() != "MQo=" {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
|
|
// test
|
|
if docs, err := buf.Read(4); err != nil ||
|
|
len(docs) != 4 ||
|
|
docs[0] != "4\n" ||
|
|
docs[1] != "3\n" ||
|
|
docs[2] != "2\n" ||
|
|
docs[3] != "1\n" ||
|
|
buf.Cached() != 3 ||
|
|
backingStore.Contents() != "MQo=" {
|
|
t.Fatalf("error reading: %e", err)
|
|
}
|
|
}
|
|
|
|
func TestClose(t *testing.T) {
|
|
// do pushes and a remove then Close. assure no error
|
|
// is the int return where I can truncate?
|
|
docCtr := 1
|
|
backingStore := NewReadWriteSeekString()
|
|
buf, e := NewDocumentBuffer(3, &backingStore)
|
|
if e != nil {
|
|
t.Fatalf("error making documentbuffer: %e", e)
|
|
}
|
|
|
|
// setup test data
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 1 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 2 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil || buf.Cached() != 3 {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
if err := buf.Push(docu(&docCtr)); err != nil ||
|
|
buf.Cached() != 3 || backingStore.Contents() != "MQo=" {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
|
|
for range 5 {
|
|
if err := buf.Push(docu(&docCtr)); err != nil {
|
|
t.Fatalf("error pushing: %e", err)
|
|
}
|
|
}
|
|
|
|
docs, err := buf.Remove(4)
|
|
if err != nil ||
|
|
len(docs) != 4 ||
|
|
buf.Cached() != 3 {
|
|
t.Fatalf("error removing: %e", err)
|
|
}
|
|
|
|
expectedDoc := "MQo=\nMgo=\nMwo=\nNAo=\nNQo=\nNgo="
|
|
idx, err := buf.Close()
|
|
if err != nil ||
|
|
idx != 24 ||
|
|
buf.Cached() != 0 ||
|
|
backingStore.Contents() != expectedDoc {
|
|
t.Fatalf("error closing: %e", err)
|
|
}
|
|
}
|
|
|
|
func TestInitialize(t *testing.T) {
|
|
backingStore := NewReadWriteSeekString()
|
|
backingStore.Write([]byte("MQo=\nMgo=\nMwo=\nNAo=\nNQo=\nNgo="))
|
|
buf, e := NewDocumentBuffer(3, &backingStore)
|
|
if e != nil {
|
|
t.Fatalf("error making documentbuffer: %e", e)
|
|
}
|
|
|
|
// test cached
|
|
if buf.Cached() != 3 {
|
|
t.Fatalf("expected 3 docs in cache")
|
|
}
|
|
|
|
// read all docs
|
|
docs, err := buf.Read(6)
|
|
if err != nil ||
|
|
len(docs) != 6 ||
|
|
docs[0] != "6\n" ||
|
|
docs[1] != "5\n" ||
|
|
docs[2] != "4\n" ||
|
|
docs[3] != "3\n" ||
|
|
docs[4] != "2\n" ||
|
|
docs[5] != "1\n" {
|
|
t.Fatalf("error reading: %e", err)
|
|
}
|
|
}
|
|
|
|
func TestApply(t *testing.T) {
|
|
backingStore := NewReadWriteSeekString()
|
|
backingStore.Write([]byte("MQo=\nMgo=\nMwo=\nNAo=\nNQo=\nNgo="))
|
|
buf, e := NewDocumentBuffer(3, &backingStore)
|
|
if e != nil {
|
|
t.Fatalf("error making documentbuffer: %e", e)
|
|
}
|
|
|
|
// test cached
|
|
if buf.Cached() != 3 {
|
|
t.Fatalf("expected 3 docs in cache")
|
|
}
|
|
|
|
count := 0
|
|
if err := buf.Apply(func(doc string) bool {
|
|
count += 1
|
|
return true
|
|
}); err != nil || count != 6 {
|
|
t.Fatalf("error applying: %e", err)
|
|
}
|
|
|
|
count = 0
|
|
if err := buf.Apply(func(doc string) bool {
|
|
if doc == "2\n" {
|
|
return false
|
|
}
|
|
count += 1
|
|
return true
|
|
}); err != nil || count != 4 {
|
|
t.Fatalf("error applying: %e", err)
|
|
}
|
|
}
|