refactor: architecture foundations (status type, schema versioning, shared mock) #107

Merged
lerko merged 3 commits from refactor/arch-foundations into main 2026-06-11 20:20:24 +00:00
7 changed files with 297 additions and 400 deletions
Showing only changes of commit 2b357341c8 - Show all commits
+4 -5
View File
@@ -9,22 +9,21 @@ import (
"time" "time"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/models" "gitea.lerkolabs.com/lerkolabs/uptop/internal/models"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/store" "gitea.lerkolabs.com/lerkolabs/uptop/internal/store/storetest"
"github.com/charmbracelet/ssh" "github.com/charmbracelet/ssh"
gossh "golang.org/x/crypto/ssh" gossh "golang.org/x/crypto/ssh"
) )
// kcMockStore implements only what keyCache and userInvalidatingStore touch; // kcMockStore embeds BaseMock for default no-ops; only GetAllUsers is
// any other Store method panics via the embedded nil interface. // overridden because the tests mutate users/err between calls.
type kcMockStore struct { type kcMockStore struct {
store.Store storetest.BaseMock
users []models.User users []models.User
err error err error
} }
func (m *kcMockStore) GetAllUsers(_ context.Context) ([]models.User, error) { return m.users, m.err } func (m *kcMockStore) GetAllUsers(_ context.Context) ([]models.User, error) { return m.users, m.err }
func (m *kcMockStore) DeleteUser(_ context.Context, _ int) error { return nil }
func testKey(t *testing.T) (string, ssh.PublicKey) { func testKey(t *testing.T) (string, ssh.PublicKey) {
t.Helper() t.Helper()
+2 -89
View File
@@ -12,100 +12,13 @@ import (
"gitea.lerkolabs.com/lerkolabs/uptop/internal/models" "gitea.lerkolabs.com/lerkolabs/uptop/internal/models"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/monitor" "gitea.lerkolabs.com/lerkolabs/uptop/internal/monitor"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/store/storetest"
) )
// --- Mock Store (minimal, for monitor.NewEngine) ---
type mockStore struct { type mockStore struct {
sites []models.Site storetest.BaseMock
} }
func (m *mockStore) Init(_ context.Context) error { return nil }
func (m *mockStore) GetSites(_ context.Context) ([]models.Site, error) { return m.sites, nil }
func (m *mockStore) AddSite(_ context.Context, _ models.Site) error { return nil }
func (m *mockStore) UpdateSite(_ context.Context, _ models.Site) error { return nil }
func (m *mockStore) UpdateSitePaused(_ context.Context, _ int, _ bool) error { return nil }
func (m *mockStore) DeleteSite(_ context.Context, _ int) error { return nil }
func (m *mockStore) GetAllAlerts(_ context.Context) ([]models.AlertConfig, error) { return nil, nil }
func (m *mockStore) GetAlert(_ context.Context, _ int) (models.AlertConfig, error) {
return models.AlertConfig{}, nil
}
func (m *mockStore) AddAlert(_ context.Context, _ string, _ string, _ map[string]string) error {
return nil
}
func (m *mockStore) UpdateAlert(_ context.Context, _ int, _ string, _ string, _ map[string]string) error {
return nil
}
func (m *mockStore) DeleteAlert(_ context.Context, _ int) error { return nil }
func (m *mockStore) GetAllUsers(_ context.Context) ([]models.User, error) { return nil, nil }
func (m *mockStore) AddUser(_ context.Context, _ string, _ string, _ string) error { return nil }
func (m *mockStore) UpdateUser(_ context.Context, _ int, _ string, _ string, _ string) error {
return nil
}
func (m *mockStore) DeleteUser(_ context.Context, _ int) error { return nil }
func (m *mockStore) SaveCheck(_ context.Context, _ int, _ int64, _ bool) error { return nil }
func (m *mockStore) SaveCheckFromNode(_ context.Context, _ int, _ string, _ int64, _ bool) error {
return nil
}
func (m *mockStore) LoadAllHistory(_ context.Context, _ int) (map[int][]models.CheckRecord, error) {
return nil, nil
}
func (m *mockStore) ExportData(_ context.Context) (models.Backup, error) { return models.Backup{}, nil }
func (m *mockStore) ImportData(_ context.Context, _ models.Backup) error { return nil }
func (m *mockStore) GetSiteByName(_ context.Context, _ string) (models.Site, error) {
return models.Site{}, nil
}
func (m *mockStore) GetAlertByName(_ context.Context, _ string) (models.AlertConfig, error) {
return models.AlertConfig{}, nil
}
func (m *mockStore) AddSiteReturningID(_ context.Context, _ models.Site) (int, error) { return 0, nil }
func (m *mockStore) AddAlertReturningID(_ context.Context, _ string, _ string, _ map[string]string) (int, error) {
return 0, nil
}
func (m *mockStore) RegisterNode(_ context.Context, _ models.ProbeNode) error { return nil }
func (m *mockStore) GetNode(_ context.Context, _ string) (models.ProbeNode, error) {
return models.ProbeNode{}, nil
}
func (m *mockStore) GetAllNodes(_ context.Context) ([]models.ProbeNode, error) { return nil, nil }
func (m *mockStore) UpdateNodeLastSeen(_ context.Context, _ string) error { return nil }
func (m *mockStore) DeleteNode(_ context.Context, _ string) error { return nil }
func (m *mockStore) LoadAlertHealth(_ context.Context) (map[int]models.AlertHealthRecord, error) {
return nil, nil
}
func (m *mockStore) SaveAlertHealth(_ context.Context, _ models.AlertHealthRecord) error { return nil }
func (m *mockStore) SaveLog(_ context.Context, _ string) error { return nil }
func (m *mockStore) PruneLogs(_ context.Context) error { return nil }
func (m *mockStore) PruneCheckHistory(_ context.Context) error { return nil }
func (m *mockStore) PruneStateChanges(_ context.Context) error { return nil }
func (m *mockStore) LoadLogs(_ context.Context, _ int) ([]string, error) { return nil, nil }
func (m *mockStore) GetActiveMaintenanceWindows(_ context.Context) ([]models.MaintenanceWindow, error) {
return nil, nil
}
func (m *mockStore) GetAllMaintenanceWindows(_ context.Context, _ int) ([]models.MaintenanceWindow, error) {
return nil, nil
}
func (m *mockStore) AddMaintenanceWindow(_ context.Context, _ models.MaintenanceWindow) error {
return nil
}
func (m *mockStore) EndMaintenanceWindow(_ context.Context, _ int) error { return nil }
func (m *mockStore) DeleteMaintenanceWindow(_ context.Context, _ int) error { return nil }
func (m *mockStore) PruneExpiredMaintenanceWindows(_ context.Context, _ time.Duration) (int64, error) {
return 0, nil
}
func (m *mockStore) IsMonitorInMaintenance(_ context.Context, _ int) (bool, error) { return false, nil }
func (m *mockStore) GetPreference(_ context.Context, _ string) (string, error) { return "", nil }
func (m *mockStore) SetPreference(_ context.Context, _ string, _ string) error { return nil }
func (m *mockStore) SaveStateChange(_ context.Context, _ int, _ string, _ string, _ string) error {
return nil
}
func (m *mockStore) GetStateChanges(_ context.Context, _ int, _ int) ([]models.StateChange, error) {
return nil, nil
}
func (m *mockStore) GetStateChangesSince(_ context.Context, _ int, _ time.Time) ([]models.StateChange, error) {
return nil, nil
}
func (m *mockStore) Close() error { return nil }
// --- Cluster Start Tests --- // --- Cluster Start Tests ---
func TestStart_LeaderMode(t *testing.T) { func TestStart_LeaderMode(t *testing.T) {
+4 -84
View File
@@ -10,97 +10,17 @@ import (
"gitea.lerkolabs.com/lerkolabs/uptop/internal/models" "gitea.lerkolabs.com/lerkolabs/uptop/internal/models"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/monitor" "gitea.lerkolabs.com/lerkolabs/uptop/internal/monitor"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/store/storetest"
) )
type mockStore struct { type mockStore struct {
storetest.BaseMock
sites []models.Site sites []models.Site
} }
func (m *mockStore) Init(_ context.Context) error { return nil } func (m *mockStore) GetSites(_ context.Context) ([]models.Site, error) {
func (m *mockStore) GetSites(_ context.Context) ([]models.Site, error) { return m.sites, nil } return m.sites, nil
func (m *mockStore) AddSite(_ context.Context, _ models.Site) error { return nil }
func (m *mockStore) UpdateSite(_ context.Context, _ models.Site) error { return nil }
func (m *mockStore) UpdateSitePaused(_ context.Context, _ int, _ bool) error { return nil }
func (m *mockStore) DeleteSite(_ context.Context, _ int) error { return nil }
func (m *mockStore) GetAllAlerts(_ context.Context) ([]models.AlertConfig, error) { return nil, nil }
func (m *mockStore) GetAlert(_ context.Context, _ int) (models.AlertConfig, error) {
return models.AlertConfig{}, nil
} }
func (m *mockStore) AddAlert(_ context.Context, _ string, _ string, _ map[string]string) error {
return nil
}
func (m *mockStore) UpdateAlert(_ context.Context, _ int, _ string, _ string, _ map[string]string) error {
return nil
}
func (m *mockStore) DeleteAlert(_ context.Context, _ int) error { return nil }
func (m *mockStore) GetAllUsers(_ context.Context) ([]models.User, error) { return nil, nil }
func (m *mockStore) AddUser(_ context.Context, _ string, _ string, _ string) error { return nil }
func (m *mockStore) UpdateUser(_ context.Context, _ int, _ string, _ string, _ string) error {
return nil
}
func (m *mockStore) DeleteUser(_ context.Context, _ int) error { return nil }
func (m *mockStore) SaveCheck(_ context.Context, _ int, _ int64, _ bool) error { return nil }
func (m *mockStore) LoadAllHistory(_ context.Context, _ int) (map[int][]models.CheckRecord, error) {
return nil, nil
}
func (m *mockStore) ExportData(_ context.Context) (models.Backup, error) { return models.Backup{}, nil }
func (m *mockStore) ImportData(_ context.Context, _ models.Backup) error { return nil }
func (m *mockStore) GetSiteByName(_ context.Context, _ string) (models.Site, error) {
return models.Site{}, nil
}
func (m *mockStore) GetAlertByName(_ context.Context, _ string) (models.AlertConfig, error) {
return models.AlertConfig{}, nil
}
func (m *mockStore) AddSiteReturningID(_ context.Context, _ models.Site) (int, error) { return 0, nil }
func (m *mockStore) AddAlertReturningID(_ context.Context, _ string, _ string, _ map[string]string) (int, error) {
return 0, nil
}
func (m *mockStore) SaveCheckFromNode(_ context.Context, _ int, _ string, _ int64, _ bool) error {
return nil
}
func (m *mockStore) RegisterNode(_ context.Context, _ models.ProbeNode) error { return nil }
func (m *mockStore) GetNode(_ context.Context, _ string) (models.ProbeNode, error) {
return models.ProbeNode{}, nil
}
func (m *mockStore) GetAllNodes(_ context.Context) ([]models.ProbeNode, error) { return nil, nil }
func (m *mockStore) UpdateNodeLastSeen(_ context.Context, _ string) error { return nil }
func (m *mockStore) DeleteNode(_ context.Context, _ string) error { return nil }
func (m *mockStore) LoadAlertHealth(_ context.Context) (map[int]models.AlertHealthRecord, error) {
return nil, nil
}
func (m *mockStore) SaveAlertHealth(_ context.Context, _ models.AlertHealthRecord) error { return nil }
func (m *mockStore) SaveLog(_ context.Context, _ string) error { return nil }
func (m *mockStore) PruneLogs(_ context.Context) error { return nil }
func (m *mockStore) PruneCheckHistory(_ context.Context) error { return nil }
func (m *mockStore) PruneStateChanges(_ context.Context) error { return nil }
func (m *mockStore) LoadLogs(_ context.Context, _ int) ([]string, error) { return nil, nil }
func (m *mockStore) GetActiveMaintenanceWindows(_ context.Context) ([]models.MaintenanceWindow, error) {
return nil, nil
}
func (m *mockStore) GetAllMaintenanceWindows(_ context.Context, _ int) ([]models.MaintenanceWindow, error) {
return nil, nil
}
func (m *mockStore) AddMaintenanceWindow(_ context.Context, _ models.MaintenanceWindow) error {
return nil
}
func (m *mockStore) EndMaintenanceWindow(_ context.Context, _ int) error { return nil }
func (m *mockStore) DeleteMaintenanceWindow(_ context.Context, _ int) error { return nil }
func (m *mockStore) PruneExpiredMaintenanceWindows(_ context.Context, _ time.Duration) (int64, error) {
return 0, nil
}
func (m *mockStore) IsMonitorInMaintenance(_ context.Context, _ int) (bool, error) { return false, nil }
func (m *mockStore) GetPreference(_ context.Context, _ string) (string, error) { return "", nil }
func (m *mockStore) SetPreference(_ context.Context, _ string, _ string) error { return nil }
func (m *mockStore) SaveStateChange(_ context.Context, _ int, _ string, _ string, _ string) error {
return nil
}
func (m *mockStore) GetStateChanges(_ context.Context, _ int, _ int) ([]models.StateChange, error) {
return nil, nil
}
func (m *mockStore) GetStateChangesSince(_ context.Context, _ int, _ time.Time) ([]models.StateChange, error) {
return nil, nil
}
func (m *mockStore) Close() error { return nil }
func TestMetricsHandler(t *testing.T) { func TestMetricsHandler(t *testing.T) {
ms := &mockStore{ ms := &mockStore{
+6 -61
View File
@@ -8,6 +8,7 @@ import (
"time" "time"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/models" "gitea.lerkolabs.com/lerkolabs/uptop/internal/models"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/store/storetest"
) )
// --- Mock Store --- // --- Mock Store ---
@@ -19,6 +20,7 @@ type savedCheck struct {
} }
type mockStore struct { type mockStore struct {
storetest.BaseMock
mu sync.Mutex mu sync.Mutex
sites []models.Site sites []models.Site
alerts map[int]models.AlertConfig alerts map[int]models.AlertConfig
@@ -38,42 +40,8 @@ func newMockStore() *mockStore {
} }
} }
func (m *mockStore) Init(context.Context) error { return nil } func (m *mockStore) GetSites(context.Context) ([]models.Site, error) { return m.sites, nil }
func (m *mockStore) GetSites(context.Context) ([]models.Site, error) { return m.sites, nil }
func (m *mockStore) AddSite(context.Context, models.Site) error { return nil }
func (m *mockStore) UpdateSite(context.Context, models.Site) error { return nil }
func (m *mockStore) UpdateSitePaused(context.Context, int, bool) error { return nil }
func (m *mockStore) DeleteSite(context.Context, int) error { return nil }
func (m *mockStore) AddAlert(context.Context, string, string, map[string]string) error { return nil }
func (m *mockStore) UpdateAlert(context.Context, int, string, string, map[string]string) error {
return nil
}
func (m *mockStore) DeleteAlert(context.Context, int) error { return nil }
func (m *mockStore) GetAllUsers(context.Context) ([]models.User, error) { return nil, nil }
func (m *mockStore) AddUser(context.Context, string, string, string) error { return nil }
func (m *mockStore) UpdateUser(context.Context, int, string, string, string) error { return nil }
func (m *mockStore) DeleteUser(context.Context, int) error { return nil }
func (m *mockStore) ExportData(context.Context) (models.Backup, error) { return models.Backup{}, nil }
func (m *mockStore) ImportData(context.Context, models.Backup) error { return nil }
func (m *mockStore) GetSiteByName(context.Context, string) (models.Site, error) {
return models.Site{}, nil
}
func (m *mockStore) AddSiteReturningID(context.Context, models.Site) (int, error) { return 0, nil }
func (m *mockStore) AddAlertReturningID(context.Context, string, string, map[string]string) (int, error) {
return 0, nil
}
func (m *mockStore) SaveCheckFromNode(context.Context, int, string, int64, bool) error { return nil }
func (m *mockStore) RegisterNode(context.Context, models.ProbeNode) error { return nil }
func (m *mockStore) GetNode(context.Context, string) (models.ProbeNode, error) {
return models.ProbeNode{}, nil
}
func (m *mockStore) GetAllNodes(context.Context) ([]models.ProbeNode, error) { return nil, nil }
func (m *mockStore) UpdateNodeLastSeen(context.Context, string) error { return nil }
func (m *mockStore) DeleteNode(context.Context, string) error { return nil }
func (m *mockStore) LoadAlertHealth(context.Context) (map[int]models.AlertHealthRecord, error) {
return nil, nil
}
func (m *mockStore) SaveAlertHealth(context.Context, models.AlertHealthRecord) error { return nil }
func (m *mockStore) GetActiveMaintenanceWindows(context.Context) ([]models.MaintenanceWindow, error) { func (m *mockStore) GetActiveMaintenanceWindows(context.Context) ([]models.MaintenanceWindow, error) {
m.mu.Lock() m.mu.Lock()
defer m.mu.Unlock() defer m.mu.Unlock()
@@ -83,25 +51,6 @@ func (m *mockStore) GetActiveMaintenanceWindows(context.Context) ([]models.Maint
} }
return windows, nil return windows, nil
} }
func (m *mockStore) GetAllMaintenanceWindows(context.Context, int) ([]models.MaintenanceWindow, error) {
return nil, nil
}
func (m *mockStore) AddMaintenanceWindow(context.Context, models.MaintenanceWindow) error { return nil }
func (m *mockStore) EndMaintenanceWindow(context.Context, int) error { return nil }
func (m *mockStore) DeleteMaintenanceWindow(context.Context, int) error { return nil }
func (m *mockStore) PruneExpiredMaintenanceWindows(context.Context, time.Duration) (int64, error) {
return 0, nil
}
func (m *mockStore) GetPreference(context.Context, string) (string, error) { return "", nil }
func (m *mockStore) SetPreference(context.Context, string, string) error { return nil }
func (m *mockStore) SaveStateChange(context.Context, int, string, string, string) error { return nil }
func (m *mockStore) GetStateChanges(context.Context, int, int) ([]models.StateChange, error) {
return nil, nil
}
func (m *mockStore) GetStateChangesSince(context.Context, int, time.Time) ([]models.StateChange, error) {
return nil, nil
}
func (m *mockStore) Close() error { return nil }
func (m *mockStore) GetAllAlerts(context.Context) ([]models.AlertConfig, error) { func (m *mockStore) GetAllAlerts(context.Context) ([]models.AlertConfig, error) {
m.mu.Lock() m.mu.Lock()
@@ -154,18 +103,14 @@ func (m *mockStore) SaveLog(_ context.Context, msg string) error {
return nil return nil
} }
func (m *mockStore) LoadLogs(_ context.Context, limit int) ([]string, error) { func (m *mockStore) LoadLogs(_ context.Context, _ int) ([]string, error) {
return m.logs, nil return m.logs, nil
} }
func (m *mockStore) LoadAllHistory(_ context.Context, limit int) (map[int][]models.CheckRecord, error) { func (m *mockStore) LoadAllHistory(_ context.Context, _ int) (map[int][]models.CheckRecord, error) {
return m.history, nil return m.history, nil
} }
func (m *mockStore) PruneLogs(context.Context) error { return nil }
func (m *mockStore) PruneCheckHistory(context.Context) error { return nil }
func (m *mockStore) PruneStateChanges(context.Context) error { return nil }
// --- Helpers --- // --- Helpers ---
func newTestEngine(ms *mockStore) *Engine { func newTestEngine(ms *mockStore) *Engine {
+3 -75
View File
@@ -13,11 +13,13 @@ import (
"gitea.lerkolabs.com/lerkolabs/uptop/internal/models" "gitea.lerkolabs.com/lerkolabs/uptop/internal/models"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/monitor" "gitea.lerkolabs.com/lerkolabs/uptop/internal/monitor"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/store/storetest"
) )
// --- Mock Store --- // --- Mock Store ---
type mockStore struct { type mockStore struct {
storetest.BaseMock
mu sync.Mutex mu sync.Mutex
sites []models.Site sites []models.Site
alerts []models.AlertConfig alerts []models.AlertConfig
@@ -33,84 +35,10 @@ func newMockStore() *mockStore {
} }
} }
func (m *mockStore) Init(_ context.Context) error { return nil } func (m *mockStore) GetSites(_ context.Context) ([]models.Site, error) { return m.sites, nil }
func (m *mockStore) GetSites(_ context.Context) ([]models.Site, error) { return m.sites, nil }
func (m *mockStore) AddSite(_ context.Context, _ models.Site) error { return nil }
func (m *mockStore) UpdateSite(_ context.Context, _ models.Site) error { return nil }
func (m *mockStore) UpdateSitePaused(_ context.Context, _ int, _ bool) error { return nil }
func (m *mockStore) DeleteSite(_ context.Context, _ int) error { return nil }
func (m *mockStore) GetAllAlerts(_ context.Context) ([]models.AlertConfig, error) { func (m *mockStore) GetAllAlerts(_ context.Context) ([]models.AlertConfig, error) {
return m.alerts, nil return m.alerts, nil
} }
func (m *mockStore) GetAlert(_ context.Context, _ int) (models.AlertConfig, error) {
return models.AlertConfig{}, nil
}
func (m *mockStore) AddAlert(_ context.Context, _ string, _ string, _ map[string]string) error {
return nil
}
func (m *mockStore) UpdateAlert(_ context.Context, _ int, _ string, _ string, _ map[string]string) error {
return nil
}
func (m *mockStore) DeleteAlert(_ context.Context, _ int) error { return nil }
func (m *mockStore) GetAllUsers(_ context.Context) ([]models.User, error) { return nil, nil }
func (m *mockStore) AddUser(_ context.Context, _ string, _ string, _ string) error { return nil }
func (m *mockStore) UpdateUser(_ context.Context, _ int, _ string, _ string, _ string) error {
return nil
}
func (m *mockStore) DeleteUser(_ context.Context, _ int) error { return nil }
func (m *mockStore) SaveCheck(_ context.Context, _ int, _ int64, _ bool) error { return nil }
func (m *mockStore) SaveCheckFromNode(_ context.Context, siteID int, nodeID string, latencyNs int64, isUp bool) error {
return nil
}
func (m *mockStore) LoadAllHistory(_ context.Context, _ int) (map[int][]models.CheckRecord, error) {
return nil, nil
}
func (m *mockStore) GetSiteByName(_ context.Context, _ string) (models.Site, error) {
return models.Site{}, nil
}
func (m *mockStore) GetAlertByName(_ context.Context, _ string) (models.AlertConfig, error) {
return models.AlertConfig{}, nil
}
func (m *mockStore) AddSiteReturningID(_ context.Context, _ models.Site) (int, error) { return 0, nil }
func (m *mockStore) AddAlertReturningID(_ context.Context, _ string, _ string, _ map[string]string) (int, error) {
return 0, nil
}
func (m *mockStore) GetAllNodes(_ context.Context) ([]models.ProbeNode, error) { return nil, nil }
func (m *mockStore) UpdateNodeLastSeen(_ context.Context, _ string) error { return nil }
func (m *mockStore) DeleteNode(_ context.Context, _ string) error { return nil }
func (m *mockStore) LoadAlertHealth(_ context.Context) (map[int]models.AlertHealthRecord, error) {
return nil, nil
}
func (m *mockStore) SaveAlertHealth(_ context.Context, _ models.AlertHealthRecord) error { return nil }
func (m *mockStore) SaveLog(_ context.Context, _ string) error { return nil }
func (m *mockStore) PruneLogs(_ context.Context) error { return nil }
func (m *mockStore) PruneCheckHistory(_ context.Context) error { return nil }
func (m *mockStore) PruneStateChanges(_ context.Context) error { return nil }
func (m *mockStore) LoadLogs(_ context.Context, _ int) ([]string, error) { return nil, nil }
func (m *mockStore) GetAllMaintenanceWindows(_ context.Context, _ int) ([]models.MaintenanceWindow, error) {
return nil, nil
}
func (m *mockStore) AddMaintenanceWindow(_ context.Context, _ models.MaintenanceWindow) error {
return nil
}
func (m *mockStore) EndMaintenanceWindow(_ context.Context, _ int) error { return nil }
func (m *mockStore) DeleteMaintenanceWindow(_ context.Context, _ int) error { return nil }
func (m *mockStore) PruneExpiredMaintenanceWindows(_ context.Context, _ time.Duration) (int64, error) {
return 0, nil
}
func (m *mockStore) IsMonitorInMaintenance(_ context.Context, _ int) (bool, error) { return false, nil }
func (m *mockStore) GetPreference(_ context.Context, _ string) (string, error) { return "", nil }
func (m *mockStore) SetPreference(_ context.Context, _ string, _ string) error { return nil }
func (m *mockStore) SaveStateChange(_ context.Context, _ int, _ string, _ string, _ string) error {
return nil
}
func (m *mockStore) GetStateChanges(_ context.Context, _ int, _ int) ([]models.StateChange, error) {
return nil, nil
}
func (m *mockStore) GetStateChangesSince(_ context.Context, _ int, _ time.Time) ([]models.StateChange, error) {
return nil, nil
}
func (m *mockStore) Close() error { return nil }
func (m *mockStore) ExportData(_ context.Context) (models.Backup, error) { func (m *mockStore) ExportData(_ context.Context) (models.Backup, error) {
return models.Backup{ return models.Backup{
+274
View File
@@ -0,0 +1,274 @@
package storetest
import (
"context"
"time"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/models"
)
// BaseMock implements store.Store with no-op defaults. Embed it in test-specific
// mocks and override only the methods you need via the exported Func fields or
// by shadowing the method on the embedding struct.
type BaseMock struct {
GetSitesFunc func(ctx context.Context) ([]models.Site, error)
AddSiteFunc func(ctx context.Context, site models.Site) error
UpdateSiteFunc func(ctx context.Context, site models.Site) error
GetAllAlertsFunc func(ctx context.Context) ([]models.AlertConfig, error)
GetAlertFunc func(ctx context.Context, id int) (models.AlertConfig, error)
GetAllUsersFunc func(ctx context.Context) ([]models.User, error)
GetAllNodesFunc func(ctx context.Context) ([]models.ProbeNode, error)
GetActiveMaintenanceWindowsFunc func(ctx context.Context) ([]models.MaintenanceWindow, error)
GetAllMaintenanceWindowsFunc func(ctx context.Context, limit int) ([]models.MaintenanceWindow, error)
IsMonitorInMaintenanceFunc func(ctx context.Context, id int) (bool, error)
LoadAlertHealthFunc func(ctx context.Context) (map[int]models.AlertHealthRecord, error)
LoadAllHistoryFunc func(ctx context.Context, limit int) (map[int][]models.CheckRecord, error)
SaveCheckFunc func(ctx context.Context, siteID int, latencyNs int64, isUp bool) error
SaveCheckFromNodeFunc func(ctx context.Context, siteID int, nodeID string, latencyNs int64, isUp bool) error
SaveLogFunc func(ctx context.Context, message string) error
SaveStateChangeFunc func(ctx context.Context, siteID int, from, to, reason string) error
SaveAlertHealthFunc func(ctx context.Context, h models.AlertHealthRecord) error
GetStateChangesFunc func(ctx context.Context, siteID, limit int) ([]models.StateChange, error)
GetStateChangesSinceFunc func(ctx context.Context, siteID int, since time.Time) ([]models.StateChange, error)
ExportDataFunc func(ctx context.Context) (models.Backup, error)
ImportDataFunc func(ctx context.Context, data models.Backup) error
RegisterNodeFunc func(ctx context.Context, node models.ProbeNode) error
GetNodeFunc func(ctx context.Context, id string) (models.ProbeNode, error)
GetPreferenceFunc func(ctx context.Context, key string) (string, error)
SetPreferenceFunc func(ctx context.Context, key, value string) error
}
func (m *BaseMock) Init(_ context.Context) error { return nil }
func (m *BaseMock) Close() error { return nil }
func (m *BaseMock) GetSites(ctx context.Context) ([]models.Site, error) {
if m.GetSitesFunc != nil {
return m.GetSitesFunc(ctx)
}
return nil, nil
}
func (m *BaseMock) AddSite(ctx context.Context, site models.Site) error {
if m.AddSiteFunc != nil {
return m.AddSiteFunc(ctx, site)
}
return nil
}
func (m *BaseMock) UpdateSite(ctx context.Context, site models.Site) error {
if m.UpdateSiteFunc != nil {
return m.UpdateSiteFunc(ctx, site)
}
return nil
}
func (m *BaseMock) UpdateSitePaused(_ context.Context, _ int, _ bool) error { return nil }
func (m *BaseMock) DeleteSite(_ context.Context, _ int) error { return nil }
func (m *BaseMock) GetAllAlerts(ctx context.Context) ([]models.AlertConfig, error) {
if m.GetAllAlertsFunc != nil {
return m.GetAllAlertsFunc(ctx)
}
return nil, nil
}
func (m *BaseMock) GetAlert(ctx context.Context, id int) (models.AlertConfig, error) {
if m.GetAlertFunc != nil {
return m.GetAlertFunc(ctx, id)
}
return models.AlertConfig{}, nil
}
func (m *BaseMock) AddAlert(_ context.Context, _ string, _ string, _ map[string]string) error {
return nil
}
func (m *BaseMock) UpdateAlert(_ context.Context, _ int, _ string, _ string, _ map[string]string) error {
return nil
}
func (m *BaseMock) DeleteAlert(_ context.Context, _ int) error { return nil }
func (m *BaseMock) GetSiteByName(_ context.Context, _ string) (models.Site, error) {
return models.Site{}, nil
}
func (m *BaseMock) GetAlertByName(_ context.Context, _ string) (models.AlertConfig, error) {
return models.AlertConfig{}, nil
}
func (m *BaseMock) AddSiteReturningID(_ context.Context, _ models.Site) (int, error) { return 0, nil }
func (m *BaseMock) AddAlertReturningID(_ context.Context, _ string, _ string, _ map[string]string) (int, error) {
return 0, nil
}
func (m *BaseMock) GetAllUsers(ctx context.Context) ([]models.User, error) {
if m.GetAllUsersFunc != nil {
return m.GetAllUsersFunc(ctx)
}
return nil, nil
}
func (m *BaseMock) AddUser(_ context.Context, _ string, _ string, _ string) error { return nil }
func (m *BaseMock) UpdateUser(_ context.Context, _ int, _ string, _ string, _ string) error {
return nil
}
func (m *BaseMock) DeleteUser(_ context.Context, _ int) error { return nil }
func (m *BaseMock) SaveCheck(ctx context.Context, siteID int, latencyNs int64, isUp bool) error {
if m.SaveCheckFunc != nil {
return m.SaveCheckFunc(ctx, siteID, latencyNs, isUp)
}
return nil
}
func (m *BaseMock) SaveCheckFromNode(ctx context.Context, siteID int, nodeID string, latencyNs int64, isUp bool) error {
if m.SaveCheckFromNodeFunc != nil {
return m.SaveCheckFromNodeFunc(ctx, siteID, nodeID, latencyNs, isUp)
}
return nil
}
func (m *BaseMock) LoadAllHistory(ctx context.Context, limit int) (map[int][]models.CheckRecord, error) {
if m.LoadAllHistoryFunc != nil {
return m.LoadAllHistoryFunc(ctx, limit)
}
return nil, nil
}
func (m *BaseMock) PruneCheckHistory(_ context.Context) error { return nil }
func (m *BaseMock) SaveStateChange(ctx context.Context, siteID int, from, to, reason string) error {
if m.SaveStateChangeFunc != nil {
return m.SaveStateChangeFunc(ctx, siteID, from, to, reason)
}
return nil
}
func (m *BaseMock) GetStateChanges(ctx context.Context, siteID, limit int) ([]models.StateChange, error) {
if m.GetStateChangesFunc != nil {
return m.GetStateChangesFunc(ctx, siteID, limit)
}
return nil, nil
}
func (m *BaseMock) GetStateChangesSince(ctx context.Context, siteID int, since time.Time) ([]models.StateChange, error) {
if m.GetStateChangesSinceFunc != nil {
return m.GetStateChangesSinceFunc(ctx, siteID, since)
}
return nil, nil
}
func (m *BaseMock) PruneStateChanges(_ context.Context) error { return nil }
func (m *BaseMock) RegisterNode(ctx context.Context, node models.ProbeNode) error {
if m.RegisterNodeFunc != nil {
return m.RegisterNodeFunc(ctx, node)
}
return nil
}
func (m *BaseMock) GetNode(ctx context.Context, id string) (models.ProbeNode, error) {
if m.GetNodeFunc != nil {
return m.GetNodeFunc(ctx, id)
}
return models.ProbeNode{}, nil
}
func (m *BaseMock) GetAllNodes(ctx context.Context) ([]models.ProbeNode, error) {
if m.GetAllNodesFunc != nil {
return m.GetAllNodesFunc(ctx)
}
return nil, nil
}
func (m *BaseMock) UpdateNodeLastSeen(_ context.Context, _ string) error { return nil }
func (m *BaseMock) DeleteNode(_ context.Context, _ string) error { return nil }
func (m *BaseMock) LoadAlertHealth(ctx context.Context) (map[int]models.AlertHealthRecord, error) {
if m.LoadAlertHealthFunc != nil {
return m.LoadAlertHealthFunc(ctx)
}
return nil, nil
}
func (m *BaseMock) SaveAlertHealth(ctx context.Context, h models.AlertHealthRecord) error {
if m.SaveAlertHealthFunc != nil {
return m.SaveAlertHealthFunc(ctx, h)
}
return nil
}
func (m *BaseMock) SaveLog(ctx context.Context, message string) error {
if m.SaveLogFunc != nil {
return m.SaveLogFunc(ctx, message)
}
return nil
}
func (m *BaseMock) LoadLogs(_ context.Context, _ int) ([]string, error) { return nil, nil }
func (m *BaseMock) PruneLogs(_ context.Context) error { return nil }
func (m *BaseMock) GetActiveMaintenanceWindows(ctx context.Context) ([]models.MaintenanceWindow, error) {
if m.GetActiveMaintenanceWindowsFunc != nil {
return m.GetActiveMaintenanceWindowsFunc(ctx)
}
return nil, nil
}
func (m *BaseMock) GetAllMaintenanceWindows(ctx context.Context, limit int) ([]models.MaintenanceWindow, error) {
if m.GetAllMaintenanceWindowsFunc != nil {
return m.GetAllMaintenanceWindowsFunc(ctx, limit)
}
return nil, nil
}
func (m *BaseMock) AddMaintenanceWindow(_ context.Context, _ models.MaintenanceWindow) error {
return nil
}
func (m *BaseMock) EndMaintenanceWindow(_ context.Context, _ int) error { return nil }
func (m *BaseMock) DeleteMaintenanceWindow(_ context.Context, _ int) error { return nil }
func (m *BaseMock) PruneExpiredMaintenanceWindows(_ context.Context, _ time.Duration) (int64, error) {
return 0, nil
}
func (m *BaseMock) IsMonitorInMaintenance(ctx context.Context, id int) (bool, error) {
if m.IsMonitorInMaintenanceFunc != nil {
return m.IsMonitorInMaintenanceFunc(ctx, id)
}
return false, nil
}
func (m *BaseMock) GetPreference(ctx context.Context, key string) (string, error) {
if m.GetPreferenceFunc != nil {
return m.GetPreferenceFunc(ctx, key)
}
return "", nil
}
func (m *BaseMock) SetPreference(ctx context.Context, key, value string) error {
if m.SetPreferenceFunc != nil {
return m.SetPreferenceFunc(ctx, key, value)
}
return nil
}
func (m *BaseMock) ExportData(ctx context.Context) (models.Backup, error) {
if m.ExportDataFunc != nil {
return m.ExportDataFunc(ctx)
}
return models.Backup{}, nil
}
func (m *BaseMock) ImportData(ctx context.Context, data models.Backup) error {
if m.ImportDataFunc != nil {
return m.ImportDataFunc(ctx, data)
}
return nil
}
+4 -86
View File
@@ -8,6 +8,7 @@ import (
"gitea.lerkolabs.com/lerkolabs/uptop/internal/models" "gitea.lerkolabs.com/lerkolabs/uptop/internal/models"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/monitor" "gitea.lerkolabs.com/lerkolabs/uptop/internal/monitor"
"gitea.lerkolabs.com/lerkolabs/uptop/internal/store/storetest"
tea "github.com/charmbracelet/bubbletea" tea "github.com/charmbracelet/bubbletea"
zone "github.com/lrstanley/bubblezone" zone "github.com/lrstanley/bubblezone"
) )
@@ -15,13 +16,14 @@ import (
// --- minimal Store mock for TUI data-flow tests --- // --- minimal Store mock for TUI data-flow tests ---
type tuiMockStore struct { type tuiMockStore struct {
storetest.BaseMock
alerts []models.AlertConfig alerts []models.AlertConfig
users []models.User users []models.User
nodes []models.ProbeNode nodes []models.ProbeNode
maint []models.MaintenanceWindow maint []models.MaintenanceWindow
stateChanges []models.StateChange stateChanges []models.StateChange
stateChangeCalls int // counts GetStateChanges hits (to prove View does no IO) stateChangeCalls int
deleteSiteCalls int // counts DeleteSite hits (to prove writes run in Cmds) deleteSiteCalls int
} }
func (m *tuiMockStore) GetAllAlerts(_ context.Context) ([]models.AlertConfig, error) { func (m *tuiMockStore) GetAllAlerts(_ context.Context) ([]models.AlertConfig, error) {
@@ -38,94 +40,10 @@ func (m *tuiMockStore) GetStateChanges(_ context.Context, _ int, _ int) ([]model
func (m *tuiMockStore) GetAllMaintenanceWindows(_ context.Context, _ int) ([]models.MaintenanceWindow, error) { func (m *tuiMockStore) GetAllMaintenanceWindows(_ context.Context, _ int) ([]models.MaintenanceWindow, error) {
return m.maint, nil return m.maint, nil
} }
func (m *tuiMockStore) Init(_ context.Context) error { return nil }
func (m *tuiMockStore) GetSites(_ context.Context) ([]models.Site, error) { return nil, nil }
func (m *tuiMockStore) AddSite(_ context.Context, _ models.Site) error { return nil }
func (m *tuiMockStore) UpdateSite(_ context.Context, _ models.Site) error { return nil }
func (m *tuiMockStore) UpdateSitePaused(_ context.Context, _ int, _ bool) error { return nil }
func (m *tuiMockStore) DeleteSite(_ context.Context, _ int) error { func (m *tuiMockStore) DeleteSite(_ context.Context, _ int) error {
m.deleteSiteCalls++ m.deleteSiteCalls++
return nil return nil
} }
func (m *tuiMockStore) GetAlert(_ context.Context, _ int) (models.AlertConfig, error) {
return models.AlertConfig{}, nil
}
func (m *tuiMockStore) AddAlert(_ context.Context, _ string, _ string, _ map[string]string) error {
return nil
}
func (m *tuiMockStore) UpdateAlert(_ context.Context, _ int, _ string, _ string, _ map[string]string) error {
return nil
}
func (m *tuiMockStore) DeleteAlert(_ context.Context, _ int) error { return nil }
func (m *tuiMockStore) GetSiteByName(_ context.Context, _ string) (models.Site, error) {
return models.Site{}, nil
}
func (m *tuiMockStore) GetAlertByName(_ context.Context, _ string) (models.AlertConfig, error) {
return models.AlertConfig{}, nil
}
func (m *tuiMockStore) AddSiteReturningID(_ context.Context, _ models.Site) (int, error) {
return 0, nil
}
func (m *tuiMockStore) AddAlertReturningID(_ context.Context, _ string, _ string, _ map[string]string) (int, error) {
return 0, nil
}
func (m *tuiMockStore) AddUser(_ context.Context, _ string, _ string, _ string) error { return nil }
func (m *tuiMockStore) UpdateUser(_ context.Context, _ int, _ string, _ string, _ string) error {
return nil
}
func (m *tuiMockStore) DeleteUser(_ context.Context, _ int) error { return nil }
func (m *tuiMockStore) SaveCheck(_ context.Context, _ int, _ int64, _ bool) error { return nil }
func (m *tuiMockStore) SaveCheckFromNode(_ context.Context, _ int, _ string, _ int64, _ bool) error {
return nil
}
func (m *tuiMockStore) LoadAllHistory(_ context.Context, _ int) (map[int][]models.CheckRecord, error) {
return nil, nil
}
func (m *tuiMockStore) PruneCheckHistory(_ context.Context) error { return nil }
func (m *tuiMockStore) SaveStateChange(_ context.Context, _ int, _ string, _ string, _ string) error {
return nil
}
func (m *tuiMockStore) GetStateChangesSince(_ context.Context, _ int, _ time.Time) ([]models.StateChange, error) {
return nil, nil
}
func (m *tuiMockStore) PruneStateChanges(_ context.Context) error { return nil }
func (m *tuiMockStore) RegisterNode(_ context.Context, _ models.ProbeNode) error { return nil }
func (m *tuiMockStore) GetNode(_ context.Context, _ string) (models.ProbeNode, error) {
return models.ProbeNode{}, nil
}
func (m *tuiMockStore) UpdateNodeLastSeen(_ context.Context, _ string) error { return nil }
func (m *tuiMockStore) DeleteNode(_ context.Context, _ string) error { return nil }
func (m *tuiMockStore) LoadAlertHealth(_ context.Context) (map[int]models.AlertHealthRecord, error) {
return nil, nil
}
func (m *tuiMockStore) SaveAlertHealth(_ context.Context, _ models.AlertHealthRecord) error {
return nil
}
func (m *tuiMockStore) SaveLog(_ context.Context, _ string) error { return nil }
func (m *tuiMockStore) LoadLogs(_ context.Context, _ int) ([]string, error) { return nil, nil }
func (m *tuiMockStore) PruneLogs(_ context.Context) error { return nil }
func (m *tuiMockStore) GetActiveMaintenanceWindows(_ context.Context) ([]models.MaintenanceWindow, error) {
return nil, nil
}
func (m *tuiMockStore) AddMaintenanceWindow(_ context.Context, _ models.MaintenanceWindow) error {
return nil
}
func (m *tuiMockStore) EndMaintenanceWindow(_ context.Context, _ int) error { return nil }
func (m *tuiMockStore) DeleteMaintenanceWindow(_ context.Context, _ int) error { return nil }
func (m *tuiMockStore) PruneExpiredMaintenanceWindows(_ context.Context, _ time.Duration) (int64, error) {
return 0, nil
}
func (m *tuiMockStore) IsMonitorInMaintenance(_ context.Context, _ int) (bool, error) {
return false, nil
}
func (m *tuiMockStore) GetPreference(_ context.Context, _ string) (string, error) { return "", nil }
func (m *tuiMockStore) SetPreference(_ context.Context, _ string, _ string) error { return nil }
func (m *tuiMockStore) ExportData(_ context.Context) (models.Backup, error) {
return models.Backup{}, nil
}
func (m *tuiMockStore) ImportData(_ context.Context, _ models.Backup) error { return nil }
func (m *tuiMockStore) Close() error { return nil }
func newTestModel(ms *tuiMockStore) Model { func newTestModel(ms *tuiMockStore) Model {
return Model{ return Model{