mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 11:30:15 +00:00
165 lines
4.3 KiB
Go
165 lines
4.3 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestPersistence_AIFindings(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
p := NewConfigPersistence(tempDir)
|
|
|
|
// Default load (empty)
|
|
data, err := p.LoadAIFindings()
|
|
require.NoError(t, err)
|
|
assert.Empty(t, data.Findings)
|
|
|
|
// Save
|
|
record := &AIFindingRecord{
|
|
ID: "id1",
|
|
Description: "analysis",
|
|
DetectedAt: time.Now(),
|
|
}
|
|
data.Findings["id1"] = record
|
|
|
|
err = p.SaveAIFindings(data.Findings) // SaveAIFindings takes map[string]*AIFindingRecord
|
|
require.NoError(t, err)
|
|
|
|
// Reload
|
|
loaded, err := p.LoadAIFindings()
|
|
require.NoError(t, err)
|
|
assert.Len(t, loaded.Findings, 1)
|
|
assert.Equal(t, "analysis", loaded.Findings["id1"].Description)
|
|
|
|
// Test Corrupt file (Unmarshal error)
|
|
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "ai_findings.json"), []byte("{invalid"), 0644))
|
|
|
|
loaded, err = p.LoadAIFindings()
|
|
// Should return empty structure on unmarshal error, not fail completely (as per code)
|
|
require.NoError(t, err)
|
|
assert.Empty(t, loaded.Findings)
|
|
}
|
|
|
|
func TestPersistence_AIUsageHistory(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
p := NewConfigPersistence(tempDir)
|
|
|
|
// Default load
|
|
data, err := p.LoadAIUsageHistory()
|
|
require.NoError(t, err)
|
|
assert.Empty(t, data.Events)
|
|
|
|
// Save
|
|
record := AIUsageEventRecord{
|
|
Timestamp: time.Now(),
|
|
RequestModel: "gpt-4",
|
|
InputTokens: 10,
|
|
OutputTokens: 20,
|
|
}
|
|
data.Events = append(data.Events, record)
|
|
|
|
err = p.SaveAIUsageHistory(data.Events)
|
|
require.NoError(t, err)
|
|
|
|
// Reload
|
|
loaded, err := p.LoadAIUsageHistory()
|
|
require.NoError(t, err)
|
|
assert.Len(t, loaded.Events, 1)
|
|
assert.Equal(t, 10, loaded.Events[0].InputTokens)
|
|
|
|
// Test Corrupt file
|
|
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "ai_usage_history.json"), []byte("{invalid"), 0644))
|
|
|
|
loaded, err = p.LoadAIUsageHistory()
|
|
// Should return empty structure
|
|
require.NoError(t, err)
|
|
assert.Empty(t, loaded.Events)
|
|
}
|
|
|
|
func TestPersistence_AIConfig(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
p := NewConfigPersistence(tempDir)
|
|
|
|
// Load default (empty/nil config if file missing? LoadAIConfig returns NewDefaultAIConfig logic inside persistence??)
|
|
// Let's check logic: LoadAIConfig reads file, if missing returns default?
|
|
loaded, err := p.LoadAIConfig()
|
|
require.NoError(t, err)
|
|
assert.NotNil(t, loaded) // Default config
|
|
|
|
// Save
|
|
cfg := NewDefaultAIConfig()
|
|
cfg.APIKey = "testkey"
|
|
err = p.SaveAIConfig(*cfg)
|
|
require.NoError(t, err)
|
|
|
|
// Reload
|
|
loaded, err = p.LoadAIConfig()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "testkey", loaded.APIKey)
|
|
|
|
// Corrupt file
|
|
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "ai.enc"), []byte("{invalid"), 0644))
|
|
// Without encryption, it's just json
|
|
// If encryption enabled (not in this test), behaviour changes.
|
|
|
|
// If crypto nil:
|
|
// Persistence.LoadAIConfig attempts decrypt if crypto != nil.
|
|
|
|
// If Unmarshal fails:
|
|
_, err = p.LoadAIConfig()
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestPersistence_AIConfig_MigratesSuggestControlLevel(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
p := NewConfigPersistence(tempDir)
|
|
|
|
cfg := NewDefaultAIConfig()
|
|
cfg.ControlLevel = "suggest"
|
|
require.NoError(t, p.SaveAIConfig(*cfg))
|
|
|
|
loaded, err := p.LoadAIConfig()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, ControlLevelControlled, loaded.ControlLevel)
|
|
|
|
updatedRaw, err := os.ReadFile(filepath.Join(tempDir, "ai.enc"))
|
|
require.NoError(t, err)
|
|
if p.crypto != nil {
|
|
decoded, err := p.crypto.Decrypt(updatedRaw)
|
|
require.NoError(t, err)
|
|
updatedRaw = decoded
|
|
}
|
|
|
|
var saved AIConfig
|
|
require.NoError(t, json.Unmarshal(updatedRaw, &saved))
|
|
assert.Equal(t, ControlLevelControlled, saved.ControlLevel)
|
|
}
|
|
|
|
func TestPersistence_PatrolRunHistory(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
p := NewConfigPersistence(tempDir)
|
|
|
|
hist, err := p.LoadPatrolRunHistory()
|
|
require.NoError(t, err)
|
|
assert.Empty(t, hist.Runs)
|
|
|
|
hist.Runs = append(hist.Runs, PatrolRunRecord{ID: "run1"})
|
|
err = p.SavePatrolRunHistory(hist.Runs)
|
|
require.NoError(t, err)
|
|
|
|
loaded, err := p.LoadPatrolRunHistory()
|
|
require.NoError(t, err)
|
|
assert.Len(t, loaded.Runs, 1)
|
|
|
|
// Corrupt
|
|
require.NoError(t, os.WriteFile(filepath.Join(tempDir, "ai_patrol_runs.json"), []byte("{invalid"), 0644))
|
|
loaded, err = p.LoadPatrolRunHistory()
|
|
require.NoError(t, err) // Returns empty on error
|
|
assert.Empty(t, loaded.Runs)
|
|
}
|