Files
kenn-io--agentsview/internal/sync/windsurf_integration_test.go
wehub-resource-sync f99010fae1
Desktop Artifacts / Desktop Build (Linux) (push) Waiting to run
Desktop Artifacts / Desktop Build (Windows) (push) Waiting to run
Desktop Artifacts / Desktop Build (Linux (arm64)) (push) Waiting to run
Desktop Artifacts (macOS) / Desktop Build (macOS (aarch64)) (push) Waiting to run
Desktop Artifacts (macOS) / Desktop Build (macOS (x86_64)) (push) Waiting to run
CI / lint (push) Failing after 1s
CI / frontend (push) Failing after 1s
CI / scripts (push) Failing after 1s
CI / Go Test (ubuntu-latest) (push) Failing after 0s
CI / frontend-node-25 (push) Failing after 1s
CI / docs (push) Failing after 0s
CI / coverage (push) Failing after 0s
CI / e2e (push) Failing after 0s
Docker / build-and-push (push) Failing after 1s
CI / integration (push) Failing after 4m43s
CI / Go Test (windows-latest) (push) Has been cancelled
CI / Desktop Unit Tests (Windows) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:36 +08:00

194 lines
5.7 KiB
Go

package sync
import (
"context"
"database/sql"
"os"
"path/filepath"
"testing"
"time"
_ "github.com/mattn/go-sqlite3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.kenn.io/agentsview/internal/dbtest"
"go.kenn.io/agentsview/internal/parser"
)
func TestSourceMtimeWindsurfUsesProviderFingerprint(t *testing.T) {
root := filepath.Join(t.TempDir(), "Windsurf", "User")
workspaceDir := filepath.Join(root, "workspaceStorage", "workspace-hash")
manifestPath := filepath.Join(workspaceDir, "workspace.json")
dbPath := filepath.Join(workspaceDir, "state.vscdb")
require.NoError(t, os.MkdirAll(workspaceDir, 0o755))
require.NoError(t, os.WriteFile(manifestPath, []byte(`{"folder":"file:///work/demo"}`), 0o644))
writeSyncWindsurfStateDB(t, dbPath, `{
"version": 1,
"sessionId": "mtime-session",
"requests": [{
"requestId": "request-1",
"message": {"text": "Question"},
"response": [{"value": "Answer"}],
"timestamp": 1710000000000
}]
}`)
database := dbtest.OpenTestDB(t)
engine := NewEngine(database, EngineConfig{
AgentDirs: map[parser.AgentType][]string{
parser.AgentWindsurf: {root},
},
Machine: "devbox",
})
defer engine.Close()
stats := engine.SyncAll(context.Background(), nil)
require.Equal(t, 1, stats.Synced)
virtualPath := dbPath + "#mtime-session"
assert.Equal(t, virtualPath, engine.FindSourceFile("windsurf:mtime-session"))
before := engine.SourceMtime("windsurf:mtime-session")
require.NotZero(t, before)
future := time.Unix(0, before).Add(2 * time.Second)
require.NoError(t, os.Chtimes(manifestPath, future, future))
after := engine.SourceMtime("windsurf:mtime-session")
assert.Greater(t, after, before)
}
func TestProcessFileWindsurfSameMtimeHashChangeReparses(t *testing.T) {
for _, tt := range []struct {
name string
seedCache bool
freshSync bool
}{
{name: "skip cache", seedCache: true},
{name: "db freshness", freshSync: true},
} {
t.Run(tt.name, func(t *testing.T) {
root := filepath.Join(t.TempDir(), "Windsurf", "User")
workspaceDir := filepath.Join(root, "workspaceStorage", "workspace-hash")
manifestPath := filepath.Join(workspaceDir, "workspace.json")
dbPath := filepath.Join(workspaceDir, "state.vscdb")
require.NoError(t, os.MkdirAll(workspaceDir, 0o755))
require.NoError(t, os.WriteFile(manifestPath, []byte(`{"folder":"file:///work/demo"}`), 0o644))
writeSyncWindsurfStateDB(t, dbPath, windsurfSyncPayload("hash-session", "Alpha reply"))
virtualPath := dbPath + "#hash-session"
database := dbtest.OpenTestDB(t)
engine := NewEngine(database, EngineConfig{
AgentDirs: map[parser.AgentType][]string{
parser.AgentWindsurf: {root},
},
Machine: "devbox",
})
defer engine.Close()
initialMtime, initialHash := syncInitialWindsurfSession(
t, engine, "hash-session",
)
infoBefore, err := os.Stat(dbPath)
require.NoError(t, err)
updateSyncWindsurfStateDB(t, dbPath, windsurfSyncPayload("hash-session", "Bravo reply"))
initialTime := time.Unix(0, initialMtime)
require.NoError(t, os.Chtimes(dbPath, initialTime, initialTime))
infoAfter, err := os.Stat(dbPath)
require.NoError(t, err)
require.Equal(t, infoBefore.Size(), infoAfter.Size(),
"test must keep size stable so hash is the only freshness signal")
if tt.seedCache {
engine.cacheSkip(
providerProcessCacheKeyWithHash(
virtualPath,
parser.AgentWindsurf,
parser.SourceFingerprint{Hash: initialHash},
),
initialMtime,
)
}
if tt.freshSync {
engine.Close()
engine = NewEngine(database, EngineConfig{
AgentDirs: map[parser.AgentType][]string{
parser.AgentWindsurf: {root},
},
Machine: "devbox",
})
defer engine.Close()
}
second := engine.processFile(context.Background(), parser.DiscoveredFile{
Path: virtualPath,
Agent: parser.AgentWindsurf,
})
require.NoError(t, second.err)
assert.False(t, second.skip)
require.Len(t, second.results, 1)
require.Len(t, second.results[0].Messages, 2)
assert.Equal(t, "Bravo reply", second.results[0].Messages[1].Content)
assert.NotEqual(t, initialHash, second.results[0].Session.File.Hash)
})
}
}
func writeSyncWindsurfStateDB(t *testing.T, dbPath, payload string) {
t.Helper()
conn, err := sql.Open("sqlite3", dbPath)
require.NoError(t, err)
defer conn.Close()
_, err = conn.Exec(`CREATE TABLE ItemTable (key TEXT PRIMARY KEY, value TEXT)`)
require.NoError(t, err)
_, err = conn.Exec(
`INSERT INTO ItemTable (key, value) VALUES (?, ?)`,
"workbench.panel.aichat.view.aichat.chatdata",
payload,
)
require.NoError(t, err)
}
func updateSyncWindsurfStateDB(t *testing.T, dbPath, payload string) {
t.Helper()
conn, err := sql.Open("sqlite3", dbPath)
require.NoError(t, err)
defer conn.Close()
_, err = conn.Exec(
`UPDATE ItemTable SET value = ? WHERE key = ?`,
payload,
"workbench.panel.aichat.view.aichat.chatdata",
)
require.NoError(t, err)
}
func syncInitialWindsurfSession(
t *testing.T,
engine *Engine,
sessionID string,
) (int64, string) {
t.Helper()
stats := engine.SyncAll(context.Background(), nil)
require.Equal(t, 1, stats.Synced)
sess, err := engine.db.GetSessionFull(
context.Background(), "windsurf:"+sessionID,
)
require.NoError(t, err)
require.NotNil(t, sess)
require.NotNil(t, sess.FileMtime)
require.NotNil(t, sess.FileHash)
require.NotZero(t, *sess.FileMtime)
require.NotEmpty(t, *sess.FileHash)
return *sess.FileMtime, *sess.FileHash
}
func windsurfSyncPayload(sessionID, assistant string) string {
return `{
"version": 1,
"sessionId": "` + sessionID + `",
"requests": [{
"requestId": "request-1",
"message": {"text": "Question"},
"response": [{"value": "` + assistant + `"}],
"timestamp": 1710000000000
}]
}`
}