166 lines
4.2 KiB
Go
166 lines
4.2 KiB
Go
package replication
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/KevoDB/kevo/pkg/config"
|
|
"github.com/KevoDB/kevo/pkg/wal"
|
|
proto "github.com/KevoDB/kevo/proto/kevo/replication"
|
|
)
|
|
|
|
// TestPrimaryCreation tests that a primary can be created with a WAL
|
|
func TestPrimaryCreation(t *testing.T) {
|
|
// Create a temporary directory for the WAL
|
|
tempDir, err := os.MkdirTemp("", "primary_creation_test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
// Create a WAL
|
|
cfg := config.NewDefaultConfig(tempDir)
|
|
w, err := wal.NewWAL(cfg, filepath.Join(tempDir, "wal"))
|
|
if err != nil {
|
|
t.Fatalf("Failed to create WAL: %v", err)
|
|
}
|
|
defer w.Close()
|
|
|
|
// Create a primary
|
|
primary, err := NewPrimary(w, DefaultPrimaryConfig())
|
|
if err != nil {
|
|
t.Fatalf("Failed to create primary: %v", err)
|
|
}
|
|
defer primary.Close()
|
|
|
|
// Check that the primary was configured correctly
|
|
if primary.wal != w {
|
|
t.Errorf("Primary has incorrect WAL reference")
|
|
}
|
|
|
|
if primary.batcher == nil {
|
|
t.Errorf("Primary has nil batcher")
|
|
}
|
|
|
|
if primary.compressor == nil {
|
|
t.Errorf("Primary has nil compressor")
|
|
}
|
|
|
|
if primary.sessions == nil {
|
|
t.Errorf("Primary has nil sessions map")
|
|
}
|
|
}
|
|
|
|
// TestPrimaryWALObserver tests that the primary correctly observes WAL events
|
|
func TestPrimaryWALObserver(t *testing.T) {
|
|
t.Skip("Skipping flaky test - will need to improve test reliability separately")
|
|
// Create a temporary directory for the WAL
|
|
tempDir, err := os.MkdirTemp("", "primary_observer_test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
// Create a WAL
|
|
cfg := config.NewDefaultConfig(tempDir)
|
|
w, err := wal.NewWAL(cfg, filepath.Join(tempDir, "wal"))
|
|
if err != nil {
|
|
t.Fatalf("Failed to create WAL: %v", err)
|
|
}
|
|
defer w.Close()
|
|
|
|
// Create a primary
|
|
primary, err := NewPrimary(w, DefaultPrimaryConfig())
|
|
if err != nil {
|
|
t.Fatalf("Failed to create primary: %v", err)
|
|
}
|
|
defer primary.Close()
|
|
|
|
// Write a single entry to the WAL
|
|
key := []byte("test-key")
|
|
value := []byte("test-value")
|
|
seq, err := w.Append(wal.OpTypePut, key, value)
|
|
if err != nil {
|
|
t.Fatalf("Failed to append to WAL: %v", err)
|
|
}
|
|
if seq != 1 {
|
|
t.Errorf("Expected sequence 1, got %d", seq)
|
|
}
|
|
|
|
// Allow some time for notifications to be processed
|
|
time.Sleep(150 * time.Millisecond)
|
|
|
|
// Verify the batcher has entries
|
|
if primary.batcher.GetBatchCount() <= 0 {
|
|
t.Errorf("Primary batcher did not receive WAL entry")
|
|
}
|
|
|
|
// Sync the WAL and verify the primary observes it
|
|
lastSyncedBefore := primary.lastSyncedSeq
|
|
err = w.Sync()
|
|
if err != nil {
|
|
t.Fatalf("Failed to sync WAL: %v", err)
|
|
}
|
|
|
|
// Allow more time for sync notification
|
|
time.Sleep(150 * time.Millisecond)
|
|
|
|
// Check that lastSyncedSeq was updated
|
|
if primary.lastSyncedSeq <= lastSyncedBefore {
|
|
t.Errorf("Primary did not update lastSyncedSeq after WAL sync")
|
|
}
|
|
}
|
|
|
|
// TestPrimarySessionManagement tests session registration and management
|
|
func TestPrimarySessionManagement(t *testing.T) {
|
|
// Create a temporary directory for the WAL
|
|
tempDir, err := os.MkdirTemp("", "primary_session_test")
|
|
if err != nil {
|
|
t.Fatalf("Failed to create temp dir: %v", err)
|
|
}
|
|
defer os.RemoveAll(tempDir)
|
|
|
|
// Create a WAL
|
|
cfg := config.NewDefaultConfig(tempDir)
|
|
w, err := wal.NewWAL(cfg, filepath.Join(tempDir, "wal"))
|
|
if err != nil {
|
|
t.Fatalf("Failed to create WAL: %v", err)
|
|
}
|
|
defer w.Close()
|
|
|
|
// Create a primary
|
|
primary, err := NewPrimary(w, DefaultPrimaryConfig())
|
|
if err != nil {
|
|
t.Fatalf("Failed to create primary: %v", err)
|
|
}
|
|
defer primary.Close()
|
|
|
|
// Register a session
|
|
session := &ReplicaSession{
|
|
ID: "test-session",
|
|
StartSequence: 0,
|
|
LastAckSequence: 0,
|
|
Connected: true,
|
|
Active: true,
|
|
LastActivity: time.Now(),
|
|
SupportedCodecs: []proto.CompressionCodec{proto.CompressionCodec_NONE},
|
|
}
|
|
|
|
primary.registerReplicaSession(session)
|
|
|
|
// Verify session was registered
|
|
if len(primary.sessions) != 1 {
|
|
t.Errorf("Expected 1 session, got %d", len(primary.sessions))
|
|
}
|
|
|
|
// Unregister session
|
|
primary.unregisterReplicaSession("test-session")
|
|
|
|
// Verify session was unregistered
|
|
if len(primary.sessions) != 0 {
|
|
t.Errorf("Expected 0 sessions after unregistering, got %d", len(primary.sessions))
|
|
}
|
|
}
|