1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-20 02:57:05 +00:00

storage/mem: implement message cap for #88

- Move message cap tests into storage test suite.
- Update change log.
This commit is contained in:
James Hillyerd
2018-03-24 14:30:53 -07:00
parent 281cc21412
commit b42ea130ea
5 changed files with 76 additions and 92 deletions

View File

@@ -22,8 +22,8 @@ import (
// TestSuite runs storage package test suite on file store.
func TestSuite(t *testing.T) {
test.StoreSuite(t, func() (storage.Store, func(), error) {
ds, _ := setupDataStore(config.Storage{})
test.StoreSuite(t, func(conf config.Storage) (storage.Store, func(), error) {
ds, _ := setupDataStore(conf)
destroy := func() {
teardownDataStore(ds)
}
@@ -144,78 +144,6 @@ func TestFSMissing(t *testing.T) {
}
}
// Test delivering several messages to the same mailbox, see if message cap works
func TestFSMessageCap(t *testing.T) {
mbCap := 10
ds, logbuf := setupDataStore(config.Storage{MailboxMsgCap: mbCap})
defer teardownDataStore(ds)
mbName := "captain"
for i := 0; i < 20; i++ {
// Add a message
subj := fmt.Sprintf("subject %v", i)
deliverMessage(ds, mbName, subj, time.Now())
t.Logf("Delivered %q", subj)
// Check number of messages
msgs, err := ds.GetMessages(mbName)
if err != nil {
t.Fatalf("Failed to GetMessages for %q: %v", mbName, err)
}
if len(msgs) > mbCap {
t.Errorf("Mailbox should be capped at %v messages, but has %v", mbCap, len(msgs))
}
// Check that the first message is correct
first := i - mbCap + 1
if first < 0 {
first = 0
}
firstSubj := fmt.Sprintf("subject %v", first)
if firstSubj != msgs[0].Subject() {
t.Errorf("Expected first subject to be %q, got %q", firstSubj, msgs[0].Subject())
}
}
if t.Failed() {
// Wait for handler to finish logging
time.Sleep(2 * time.Second)
// Dump buffered log data if there was a failure
_, _ = io.Copy(os.Stderr, logbuf)
}
}
// Test delivering several messages to the same mailbox, see if no message cap works
func TestFSNoMessageCap(t *testing.T) {
mbCap := 0
ds, logbuf := setupDataStore(config.Storage{MailboxMsgCap: mbCap})
defer teardownDataStore(ds)
mbName := "captain"
for i := 0; i < 20; i++ {
// Add a message
subj := fmt.Sprintf("subject %v", i)
deliverMessage(ds, mbName, subj, time.Now())
t.Logf("Delivered %q", subj)
// Check number of messages
msgs, err := ds.GetMessages(mbName)
if err != nil {
t.Fatalf("Failed to GetMessages for %q: %v", mbName, err)
}
if len(msgs) != i+1 {
t.Errorf("Expected %v messages, got %v", i+1, len(msgs))
}
}
if t.Failed() {
// Wait for handler to finish logging
time.Sleep(2 * time.Second)
// Dump buffered log data if there was a failure
_, _ = io.Copy(os.Stderr, logbuf)
}
}
// Test Get the latest message
func TestGetLatestMessage(t *testing.T) {
ds, logbuf := setupDataStore(config.Storage{})

View File

@@ -14,12 +14,14 @@ import (
type Store struct {
sync.Mutex
boxes map[string]*mbox
cap int
}
type mbox struct {
sync.RWMutex
name string
counter int
last int
first int
messages map[string]*Message
}
@@ -29,6 +31,7 @@ var _ storage.Store = &Store{}
func New(cfg config.Storage) (storage.Store, error) {
return &Store{
boxes: make(map[string]*mbox),
cap: cfg.MailboxMsgCap,
}, nil
}
@@ -46,10 +49,10 @@ func (s *Store) AddMessage(message storage.Message) (id string, err error) {
return
}
// Generate message ID.
mb.counter++
id = strconv.Itoa(mb.counter)
mb.last++
id = strconv.Itoa(mb.last)
m := &Message{
index: mb.counter,
index: mb.last,
mailbox: message.Mailbox(),
id: id,
from: message.From(),
@@ -59,6 +62,13 @@ func (s *Store) AddMessage(message storage.Message) (id string, err error) {
source: source,
}
mb.messages[id] = m
if s.cap > 0 {
// Enforce cap.
for len(mb.messages) > s.cap {
delete(mb.messages, strconv.Itoa(mb.first))
mb.first++
}
}
})
return id, err
}
@@ -121,7 +131,7 @@ func (s *Store) VisitMailboxes(f func([]storage.Message) (cont bool)) error {
}
// withMailbox gets or creates a mailbox, locks it, then calls f.
func (s *Store) withMailbox(mailbox string, rw bool, f func(mb *mbox)) {
func (s *Store) withMailbox(mailbox string, writeLock bool, f func(mb *mbox)) {
s.Lock()
mb, ok := s.boxes[mailbox]
if !ok {
@@ -133,13 +143,13 @@ func (s *Store) withMailbox(mailbox string, rw bool, f func(mb *mbox)) {
s.boxes[mailbox] = mb
}
s.Unlock()
if rw {
if writeLock {
mb.Lock()
} else {
mb.RLock()
}
defer func() {
if rw {
if writeLock {
mb.Unlock()
} else {
mb.RUnlock()

View File

@@ -10,8 +10,8 @@ import (
// TestSuite runs storage package test suite on file store.
func TestSuite(t *testing.T) {
test.StoreSuite(t, func() (storage.Store, func(), error) {
s, _ := New(config.Storage{})
test.StoreSuite(t, func(conf config.Storage) (storage.Store, func(), error) {
s, _ := New(conf)
destroy := func() {}
return s, destroy, nil
})