network/pkg/rqlite/metadata_test.go

240 lines
5.5 KiB
Go

package rqlite
import (
"sync"
"testing"
"time"
)
func TestMetadataStore_GetSetDatabase(t *testing.T) {
store := NewMetadataStore()
dbMeta := &DatabaseMetadata{
DatabaseName: "testdb",
NodeIDs: []string{"node1", "node2", "node3"},
PortMappings: map[string]PortPair{
"node1": {HTTPPort: 5001, RaftPort: 7001},
"node2": {HTTPPort: 5002, RaftPort: 7002},
"node3": {HTTPPort: 5003, RaftPort: 7003},
},
Status: StatusActive,
CreatedAt: time.Now(),
LastAccessed: time.Now(),
VectorClock: NewVectorClock(),
}
store.UpsertDatabase(dbMeta)
retrieved := store.GetDatabase("testdb")
if retrieved == nil {
t.Fatal("Expected to retrieve database, got nil")
}
if retrieved.DatabaseName != "testdb" {
t.Errorf("Expected database name testdb, got %s", retrieved.DatabaseName)
}
if len(retrieved.NodeIDs) != 3 {
t.Errorf("Expected 3 nodes, got %d", len(retrieved.NodeIDs))
}
if retrieved.Status != StatusActive {
t.Errorf("Expected status active, got %s", retrieved.Status)
}
}
func TestMetadataStore_DeleteDatabase(t *testing.T) {
store := NewMetadataStore()
dbMeta := &DatabaseMetadata{
DatabaseName: "testdb",
NodeIDs: []string{"node1"},
PortMappings: make(map[string]PortPair),
Status: StatusActive,
VectorClock: NewVectorClock(),
}
store.UpsertDatabase(dbMeta)
// Verify it's there
if store.GetDatabase("testdb") == nil {
t.Fatal("Expected database to exist")
}
// Delete it
store.DeleteDatabase("testdb")
// Verify it's gone
if store.GetDatabase("testdb") != nil {
t.Error("Expected database to be deleted")
}
}
func TestMetadataStore_ListDatabases(t *testing.T) {
store := NewMetadataStore()
// Add multiple databases
for i := 1; i <= 5; i++ {
dbMeta := &DatabaseMetadata{
DatabaseName: string(rune('a' + i)),
NodeIDs: []string{"node1"},
PortMappings: make(map[string]PortPair),
Status: StatusActive,
VectorClock: NewVectorClock(),
}
store.UpsertDatabase(dbMeta)
}
databases := store.GetAllDatabases()
if len(databases) != 5 {
t.Errorf("Expected 5 databases, got %d", len(databases))
}
}
func TestMetadataStore_ConcurrentAccess(t *testing.T) {
store := NewMetadataStore()
var wg sync.WaitGroup
// Spawn multiple goroutines for concurrent writes
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
dbMeta := &DatabaseMetadata{
DatabaseName: string(rune('a' + id)),
NodeIDs: []string{"node1"},
PortMappings: make(map[string]PortPair),
Status: StatusActive,
VectorClock: NewVectorClock(),
}
store.UpsertDatabase(dbMeta)
}(i)
}
// Spawn multiple goroutines for concurrent reads
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
_ = store.GetDatabase(string(rune('a' + id)))
_ = store.GetAllDatabases()
}(i)
}
wg.Wait()
// Verify all databases were added
databases := store.GetAllDatabases()
if len(databases) != 10 {
t.Errorf("Expected 10 databases after concurrent writes, got %d", len(databases))
}
}
func TestMetadataStore_NodeCapacity(t *testing.T) {
store := NewMetadataStore()
nodeCapacity := &NodeCapacity{
NodeID: "node1",
MaxDatabases: 100,
CurrentDatabases: 5,
AvailablePortRange: PortRange{
HTTPStart: 5001,
HTTPEnd: 5999,
RaftStart: 7001,
RaftEnd: 7999,
},
LastHealthCheck: time.Now(),
IsHealthy: true,
}
store.UpsertNodeCapacity(nodeCapacity)
retrieved := store.GetNode("node1")
if retrieved == nil {
t.Fatal("Expected to retrieve node capacity, got nil")
}
if retrieved.MaxDatabases != 100 {
t.Errorf("Expected max databases 100, got %d", retrieved.MaxDatabases)
}
if retrieved.CurrentDatabases != 5 {
t.Errorf("Expected current databases 5, got %d", retrieved.CurrentDatabases)
}
if !retrieved.IsHealthy {
t.Error("Expected node to be healthy")
}
}
func TestMetadataStore_UpdateNodeCapacity(t *testing.T) {
store := NewMetadataStore()
nodeCapacity := &NodeCapacity{
NodeID: "node1",
MaxDatabases: 100,
CurrentDatabases: 5,
IsHealthy: true,
}
store.UpsertNodeCapacity(nodeCapacity)
// Update capacity
nodeCapacity.CurrentDatabases = 10
nodeCapacity.IsHealthy = false
store.UpsertNodeCapacity(nodeCapacity)
retrieved := store.GetNode("node1")
if retrieved.CurrentDatabases != 10 {
t.Errorf("Expected current databases 10, got %d", retrieved.CurrentDatabases)
}
if retrieved.IsHealthy {
t.Error("Expected node to be unhealthy after update")
}
}
func TestMetadataStore_ListNodes(t *testing.T) {
store := NewMetadataStore()
// Add multiple nodes
for i := 1; i <= 3; i++ {
nodeCapacity := &NodeCapacity{
NodeID: string(rune('A' + i)),
MaxDatabases: 100,
CurrentDatabases: i * 5,
IsHealthy: true,
}
store.UpsertNodeCapacity(nodeCapacity)
}
nodes := store.GetAllNodeCapacities()
if len(nodes) != 3 {
t.Errorf("Expected 3 nodes, got %d", len(nodes))
}
}
func TestMetadataStore_UpdateDatabase(t *testing.T) {
store := NewMetadataStore()
dbMeta := &DatabaseMetadata{
DatabaseName: "testdb",
NodeIDs: []string{"node1"},
PortMappings: make(map[string]PortPair),
Status: StatusInitializing,
VectorClock: NewVectorClock(),
}
store.UpsertDatabase(dbMeta)
// Update status
dbMeta.Status = StatusActive
dbMeta.LastAccessed = time.Now()
store.UpsertDatabase(dbMeta)
retrieved := store.GetDatabase("testdb")
if retrieved.Status != StatusActive {
t.Errorf("Expected status active, got %s", retrieved.Status)
}
}