Files
osmedeus/internal/database/diff_test.go
T
j3ssie 1403d20a4d feat: add LLM step executor with vision and tool support, event workflow system, and inheritance
- Add LLM executor supporting OpenAI vision, tool calling, embeddings, and structured outputs
- Introduce event emitter/receiver workflows with deduplication and filtering (generate_event functions)
- Add workflow extends/override system enabling inheritance chains and step merge modes
- Update function naming to snake_case across all testdata (fileExists→file_exists, etc.)
- Add comprehensive test fixtures for linter, events, CDN, step dependencies, and extends workflows
2026-01-20 18:23:57 +08:00

236 lines
5.9 KiB
Go

package database
import (
"context"
"path/filepath"
"testing"
"time"
"github.com/j3ssie/osmedeus/v5/internal/config"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func setupDiffTestDB(t *testing.T) func() {
tmpDir := t.TempDir()
dbPath := filepath.Join(tmpDir, "test_diff.sqlite")
cfg := &config.Config{
BaseFolder: tmpDir,
Database: config.DatabaseConfig{
DBEngine: "sqlite",
DBPath: dbPath,
},
}
_, err := Connect(cfg)
require.NoError(t, err)
ctx := context.Background()
require.NoError(t, Migrate(ctx))
return func() {
_ = Close()
SetDB(nil)
}
}
func TestGetAssetDiff_Added(t *testing.T) {
cleanup := setupDiffTestDB(t)
defer cleanup()
ctx := context.Background()
workspace := "test-workspace"
now := time.Now()
fromTime := now.Add(-1 * time.Hour)
toTime := now
// Create a baseline asset (before fromTime)
oldAsset := &Asset{
Workspace: workspace,
AssetValue: "old.example.com",
URL: "https://old.example.com",
StatusCode: 200,
CreatedAt: fromTime.Add(-2 * time.Hour),
UpdatedAt: fromTime.Add(-2 * time.Hour),
LastSeenAt: fromTime.Add(-1 * time.Hour),
}
_, err := GetDB().NewInsert().Model(oldAsset).Exec(ctx)
require.NoError(t, err)
// Create a new asset (after fromTime)
newAsset := &Asset{
Workspace: workspace,
AssetValue: "new.example.com",
URL: "https://new.example.com",
StatusCode: 200,
CreatedAt: now.Add(-30 * time.Minute),
UpdatedAt: now.Add(-30 * time.Minute),
LastSeenAt: now,
}
_, err = GetDB().NewInsert().Model(newAsset).Exec(ctx)
require.NoError(t, err)
// Get diff
diff, err := GetAssetDiff(ctx, workspace, fromTime, toTime)
require.NoError(t, err)
// Assert
assert.Equal(t, workspace, diff.WorkspaceName)
assert.Equal(t, 1, diff.Summary.TotalAdded)
assert.Len(t, diff.Added, 1)
assert.Equal(t, "new.example.com", diff.Added[0].AssetValue)
}
func TestGetAssetDiff_Removed(t *testing.T) {
cleanup := setupDiffTestDB(t)
defer cleanup()
ctx := context.Background()
workspace := "test-workspace"
now := time.Now()
fromTime := now.Add(-1 * time.Hour)
toTime := now
// Create an old asset that hasn't been seen since before fromTime
oldAsset := &Asset{
Workspace: workspace,
AssetValue: "stale.example.com",
URL: "https://stale.example.com",
StatusCode: 200,
CreatedAt: fromTime.Add(-48 * time.Hour),
UpdatedAt: fromTime.Add(-48 * time.Hour),
LastSeenAt: fromTime.Add(-24 * time.Hour), // Last seen 24 hours before fromTime
}
_, err := GetDB().NewInsert().Model(oldAsset).Exec(ctx)
require.NoError(t, err)
// Get diff
diff, err := GetAssetDiff(ctx, workspace, fromTime, toTime)
require.NoError(t, err)
// Assert
assert.Equal(t, 1, diff.Summary.TotalRemoved)
assert.Len(t, diff.Removed, 1)
assert.Equal(t, "stale.example.com", diff.Removed[0].AssetValue)
}
func TestGetAssetDiff_Changed(t *testing.T) {
cleanup := setupDiffTestDB(t)
defer cleanup()
ctx := context.Background()
workspace := "test-workspace"
now := time.Now()
fromTime := now.Add(-1 * time.Hour)
toTime := now
// Create an asset that was created before fromTime but updated within the range
changedAsset := &Asset{
Workspace: workspace,
AssetValue: "changed.example.com",
URL: "https://changed.example.com",
StatusCode: 200,
CreatedAt: fromTime.Add(-2 * time.Hour), // Created before fromTime
UpdatedAt: now.Add(-30 * time.Minute), // Updated within range
LastSeenAt: now,
}
_, err := GetDB().NewInsert().Model(changedAsset).Exec(ctx)
require.NoError(t, err)
// Get diff
diff, err := GetAssetDiff(ctx, workspace, fromTime, toTime)
require.NoError(t, err)
// Assert
assert.Equal(t, 1, diff.Summary.TotalChanged)
assert.Len(t, diff.Changed, 1)
assert.Equal(t, "changed.example.com", diff.Changed[0].AssetValue)
}
func TestGetAssetDiff_Empty(t *testing.T) {
cleanup := setupDiffTestDB(t)
defer cleanup()
ctx := context.Background()
workspace := "empty-workspace"
now := time.Now()
fromTime := now.Add(-1 * time.Hour)
toTime := now
// Get diff for empty workspace
diff, err := GetAssetDiff(ctx, workspace, fromTime, toTime)
require.NoError(t, err)
// Assert
assert.Equal(t, workspace, diff.WorkspaceName)
assert.Equal(t, 0, diff.Summary.TotalAdded)
assert.Equal(t, 0, diff.Summary.TotalRemoved)
assert.Equal(t, 0, diff.Summary.TotalChanged)
assert.Empty(t, diff.Added)
assert.Empty(t, diff.Removed)
assert.Empty(t, diff.Changed)
}
func TestGetAssetDiff_NoDatabase(t *testing.T) {
// Ensure db is nil
originalDB := db
db = nil
defer func() { db = originalDB }()
ctx := context.Background()
diff, err := GetAssetDiff(ctx, "test", time.Now().Add(-1*time.Hour), time.Now())
assert.Error(t, err)
assert.Nil(t, diff)
assert.Contains(t, err.Error(), "database not connected")
}
func TestGetVulnerabilityDiff_Added(t *testing.T) {
cleanup := setupDiffTestDB(t)
defer cleanup()
ctx := context.Background()
workspace := "test-workspace"
now := time.Now()
fromTime := now.Add(-1 * time.Hour)
toTime := now
// Create a new vulnerability (after fromTime)
newVuln := &Vulnerability{
Workspace: workspace,
VulnInfo: "CVE-2024-1234",
VulnTitle: "Test Vulnerability",
Severity: "high",
AssetValue: "vulnerable.example.com",
CreatedAt: now.Add(-30 * time.Minute),
UpdatedAt: now.Add(-30 * time.Minute),
LastSeenAt: now,
}
_, err := GetDB().NewInsert().Model(newVuln).Exec(ctx)
require.NoError(t, err)
// Get diff
diff, err := GetVulnerabilityDiff(ctx, workspace, fromTime, toTime)
require.NoError(t, err)
// Assert
assert.Equal(t, workspace, diff.WorkspaceName)
assert.Equal(t, 1, diff.Summary.TotalAdded)
assert.Len(t, diff.Added, 1)
assert.Equal(t, "CVE-2024-1234", diff.Added[0].VulnInfo)
}
func TestImportStats(t *testing.T) {
stats := ImportStats{
New: 5,
Updated: 3,
Unchanged: 10,
Errors: 2,
}
assert.Equal(t, 5, stats.New)
assert.Equal(t, 3, stats.Updated)
assert.Equal(t, 10, stats.Unchanged)
assert.Equal(t, 2, stats.Errors)
}