test: add missing tests and fix hanging transport test
New test packages: - config/loader_test.go: 5 tests (valid, minimal, missing file, pulsar-only, defaults) - serial/serial_test.go: 6 tests (interface, read, EOF, close, empty) - app/app_test.go: 5 tests (New, dispatch store/send, error handling, ctx cancellation) Enhanced test packages: - storage/store_test.go: +3 tests (concurrent insert, close/reopen, init clears) - telegram/parser_test.go: +5 tests (concurrency, rawLog, empty, multiline, removeEmpty) - transport/transport_test.go: +7 tests, +fixes Fixes: - app.go: store field type *storage.Store -> storage.Repository (supports mocking) - transport_test: fix net.Pipe() sync deadlock in SetConnClosesPrevious - transport_test: fix MultiSender_ErrorPropagation expectations Results: 6 packages, 30+ tests, all pass with -race
This commit is contained in:
@@ -2,6 +2,7 @@ package storage
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -95,3 +96,99 @@ func TestStore_Empty(t *testing.T) {
|
||||
t.Errorf("expected 0 telegrams, got %d", len(telegrams))
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_ConcurrentInsert(t *testing.T) {
|
||||
dbFile := "test_concurrent.db"
|
||||
defer os.Remove(dbFile)
|
||||
|
||||
s, err := New(dbFile, true)
|
||||
if err != nil {
|
||||
t.Fatalf("New() failed: %v", err)
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
const numGoroutines = 10
|
||||
const insertsPerGoroutine = 10
|
||||
|
||||
for i := 0; i < numGoroutines; i++ {
|
||||
wg.Add(1)
|
||||
go func(id int) {
|
||||
defer wg.Done()
|
||||
for j := 0; j < insertsPerGoroutine; j++ {
|
||||
telegram := "ZCZC CONCURRENT MSG"
|
||||
if err := s.Insert(telegram); err != nil {
|
||||
t.Errorf("concurrent Insert() failed: %v", err)
|
||||
}
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
count, err := s.CountUnprocessed()
|
||||
if err != nil {
|
||||
t.Fatalf("CountUnprocessed() after concurrent inserts failed: %v", err)
|
||||
}
|
||||
expected := int64(numGoroutines * insertsPerGoroutine)
|
||||
if count != expected {
|
||||
t.Errorf("expected %d unprocessed, got %d", expected, count)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_CloseAndReopen(t *testing.T) {
|
||||
dbFile := "test_reopen.db"
|
||||
defer os.Remove(dbFile)
|
||||
|
||||
// Create and insert
|
||||
s, err := New(dbFile, true)
|
||||
if err != nil {
|
||||
t.Fatalf("New() failed: %v", err)
|
||||
}
|
||||
if err := s.Insert("ZCZC PERSIST NNNN"); err != nil {
|
||||
t.Fatalf("Insert() failed: %v", err)
|
||||
}
|
||||
s.Close()
|
||||
|
||||
// Reopen without init flag
|
||||
s2, err := New(dbFile, false)
|
||||
if err != nil {
|
||||
t.Fatalf("New() reopen failed: %v", err)
|
||||
}
|
||||
defer s2.Close()
|
||||
|
||||
count, err := s2.CountUnprocessed()
|
||||
if err != nil {
|
||||
t.Fatalf("CountUnprocessed() on reopened db failed: %v", err)
|
||||
}
|
||||
if count != 1 {
|
||||
t.Errorf("expected 1 unprocessed after reopen, got %d", count)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStore_InitClearsDatabase(t *testing.T) {
|
||||
dbFile := "test_init_clear.db"
|
||||
defer os.Remove(dbFile)
|
||||
|
||||
// Create and insert
|
||||
s, err := New(dbFile, false)
|
||||
if err != nil {
|
||||
t.Fatalf("New() failed: %v", err)
|
||||
}
|
||||
s.Insert("ZCZC WILL BE CLEARED NNNN")
|
||||
s.Close()
|
||||
|
||||
// Reopen with init=true (should recreate)
|
||||
s2, err := New(dbFile, true)
|
||||
if err != nil {
|
||||
t.Fatalf("New() with init=true failed: %v", err)
|
||||
}
|
||||
defer s2.Close()
|
||||
|
||||
count, err := s2.CountUnprocessed()
|
||||
if err != nil {
|
||||
t.Fatalf("CountUnprocessed() failed: %v", err)
|
||||
}
|
||||
if count != 0 {
|
||||
t.Errorf("expected 0 unprocessed after init, got %d", count)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user