Initial commit
This commit is contained in:
145
internal/poster/queue_test.go
Normal file
145
internal/poster/queue_test.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package poster
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"pete/internal/config"
|
||||
"pete/internal/storage"
|
||||
)
|
||||
|
||||
// mockMatrix implements the subset of matrix.Client that Queue needs.
|
||||
// We test via the public Enqueue/Start interface and check storage state.
|
||||
|
||||
func setupTestEnv(t *testing.T) {
|
||||
t.Helper()
|
||||
dbPath := filepath.Join(t.TempDir(), "test.db")
|
||||
if err := storage.Init(dbPath); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { storage.Close() })
|
||||
}
|
||||
|
||||
func TestQueue_EnqueueAndDrain(t *testing.T) {
|
||||
setupTestEnv(t)
|
||||
|
||||
q := &Queue{
|
||||
queues: make(map[string][]QueueItem),
|
||||
config: config.PostingConfig{
|
||||
MinIntervalSeconds: 0,
|
||||
BurstCapCount: 10,
|
||||
BurstCapWindowSeconds: 1800,
|
||||
},
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
// Enqueue directly (bypass ChannelRoomID check)
|
||||
q.mu.Lock()
|
||||
q.queues["tech"] = append(q.queues["tech"], QueueItem{
|
||||
GUID: "g1",
|
||||
Channel: "tech",
|
||||
})
|
||||
q.mu.Unlock()
|
||||
|
||||
// Verify item is in queue
|
||||
q.mu.Lock()
|
||||
if len(q.queues["tech"]) != 1 {
|
||||
t.Fatalf("expected 1 item in queue, got %d", len(q.queues["tech"]))
|
||||
}
|
||||
q.mu.Unlock()
|
||||
}
|
||||
|
||||
func TestQueueItem_MaxRetries(t *testing.T) {
|
||||
// Verify the retry counter works
|
||||
item := QueueItem{GUID: "g1", Channel: "tech", retries: 0}
|
||||
item.retries++
|
||||
if item.retries != 1 {
|
||||
t.Errorf("expected retries=1, got %d", item.retries)
|
||||
}
|
||||
item.retries++
|
||||
item.retries++
|
||||
if item.retries < maxRetries {
|
||||
t.Errorf("expected retries >= maxRetries after 3 increments, got %d", item.retries)
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueue_StartAndWait(t *testing.T) {
|
||||
setupTestEnv(t)
|
||||
|
||||
q := &Queue{
|
||||
queues: make(map[string][]QueueItem),
|
||||
config: config.PostingConfig{
|
||||
MinIntervalSeconds: 0,
|
||||
BurstCapCount: 10,
|
||||
BurstCapWindowSeconds: 1800,
|
||||
},
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
q.Start(ctx)
|
||||
}()
|
||||
|
||||
// Cancel immediately — Start should return promptly
|
||||
cancel()
|
||||
|
||||
done := make(chan struct{})
|
||||
go func() {
|
||||
q.Wait()
|
||||
close(done)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-done:
|
||||
// good
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatal("queue.Wait() did not return after cancel")
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueue_BurstCap(t *testing.T) {
|
||||
setupTestEnv(t)
|
||||
|
||||
cfg := config.PostingConfig{
|
||||
MinIntervalSeconds: 0,
|
||||
BurstCapCount: 2,
|
||||
BurstCapWindowSeconds: 3600,
|
||||
}
|
||||
|
||||
q := &Queue{
|
||||
queues: make(map[string][]QueueItem),
|
||||
config: cfg,
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
|
||||
// Simulate 2 posts already in window
|
||||
now := time.Now().Unix()
|
||||
storage.Get().Exec(`INSERT INTO post_log (guid, channel, event_id, posted_at) VALUES (?, ?, ?, ?)`,
|
||||
"prev1", "tech", "$e1", now-100)
|
||||
storage.Get().Exec(`INSERT INTO post_log (guid, channel, event_id, posted_at) VALUES (?, ?, ?, ?)`,
|
||||
"prev2", "tech", "$e2", now-50)
|
||||
|
||||
// Queue a new item
|
||||
q.mu.Lock()
|
||||
q.queues["tech"] = []QueueItem{{GUID: "g3", Channel: "tech"}}
|
||||
q.mu.Unlock()
|
||||
|
||||
// drainChannel should not post (burst cap reached)
|
||||
q.drainChannel("tech")
|
||||
|
||||
q.mu.Lock()
|
||||
remaining := len(q.queues["tech"])
|
||||
q.mu.Unlock()
|
||||
|
||||
if remaining != 1 {
|
||||
t.Errorf("expected item to remain in queue (burst cap), got %d remaining", remaining)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user