Files
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

253 lines
5.3 KiB
Go

package postgres
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.kenn.io/agentsview/internal/db"
)
func testDB(t *testing.T) *db.DB {
t.Helper()
d, err := db.Open(t.TempDir() + "/test.db")
require.NoError(t, err, "opening test db")
t.Cleanup(func() { d.Close() })
return d
}
func TestIsUndefinedTable(t *testing.T) {
tests := []struct {
name string
err error
want bool
}{
{"nil", nil, false},
{
"unrelated error",
errors.New("connection refused"),
false,
},
{
"generic does not exist",
errors.New(
`column "foo" does not exist`,
),
false,
},
{
"SQLSTATE 42P01",
errors.New(
`ERROR: relation "sessions" ` +
`does not exist (SQLSTATE 42P01)`,
),
true,
},
{
"bare SQLSTATE",
errors.New("42P01"),
true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, isUndefinedTable(tt.err))
})
}
}
func TestScopedSyncStateStoreMigratesLegacyState(t *testing.T) {
local := testDB(t)
require.NoError(t, local.SetSyncState(
"last_push_at",
"2026-03-11T12:34:56.123Z",
))
require.NoError(t, local.SetSyncState(
lastPushBoundaryStateKey,
`{"cutoff":"2026-03-11T12:34:56.123Z"}`,
))
require.NoError(t, local.SetSyncState(
lastPushTargetFingerprintKey,
"fingerprint-a",
))
require.NoError(t, local.SetSyncState(
pushMarkerIDStateKey,
"marker-a",
))
store := newScopedSyncStateStore(local, "work", true)
lastPush, err := store.GetSyncState("last_push_at")
require.NoError(t, err)
assert.Equal(t, "2026-03-11T12:34:56.123Z", lastPush)
for _, key := range []string{
"last_push_at",
lastPushBoundaryStateKey,
lastPushTargetFingerprintKey,
} {
legacyValue, err := local.GetSyncState(key)
require.NoError(t, err)
assert.Empty(t, legacyValue)
scopedValue, err := local.GetSyncState(key + ":work")
require.NoError(t, err)
assert.NotEmpty(t, scopedValue)
}
legacyMarker, err := local.GetSyncState(pushMarkerIDStateKey)
require.NoError(t, err)
assert.Equal(t, "marker-a", legacyMarker)
scopedMarker, err := local.GetSyncState(
pushMarkerIDStateKey + ":work",
)
require.NoError(t, err)
assert.Empty(t, scopedMarker)
}
func TestScopedSyncStateStoreNonDefaultTargetDoesNotMigrateLegacyState(t *testing.T) {
local := testDB(t)
require.NoError(t, local.SetSyncState(
"last_push_at",
"2026-03-11T12:34:56.123Z",
))
store := newScopedSyncStateStore(local, "archive", false)
got, err := store.GetSyncState("last_push_at")
require.NoError(t, err)
assert.Empty(t, got)
legacyValue, err := local.GetSyncState("last_push_at")
require.NoError(t, err)
assert.Equal(t, "2026-03-11T12:34:56.123Z", legacyValue)
}
func TestScopedSyncStateStoreLegacyModeUsesUnscopedKeys(t *testing.T) {
local := testDB(t)
store := newScopedSyncStateStore(local, "", false)
require.NoError(t, store.SetSyncState(
"last_push_at",
"2026-03-11T12:34:56.123Z",
))
got, err := local.GetSyncState("last_push_at")
require.NoError(t, err)
assert.Equal(t, "2026-03-11T12:34:56.123Z", got)
}
func TestPushSyncStateScopeIncludesProjectFilters(t *testing.T) {
assert.Equal(t, "", pushSyncStateScope("", nil, nil))
assert.Equal(t, "work", pushSyncStateScope("work", nil, nil))
includeAB := pushSyncStateScope(
"work",
[]string{"beta", "alpha"},
nil,
)
includeBA := pushSyncStateScope(
"work",
[]string{"alpha", "beta"},
nil,
)
excludeAB := pushSyncStateScope(
"work",
nil,
[]string{"alpha", "beta"},
)
includeAExcludeB := pushSyncStateScope(
"work",
[]string{"alpha"},
[]string{"beta"},
)
defaultIncludeAB := pushSyncStateScope(
"",
[]string{"alpha", "beta"},
nil,
)
assert.Equal(t, includeAB, includeBA)
assert.NotEmpty(t, includeAB)
assert.NotEqual(t, "work", includeAB)
assert.NotEqual(t, includeAB, excludeAB)
assert.NotEqual(t, pushSyncStateScope("work", []string{"alpha"}, nil),
includeAExcludeB)
assert.NotEqual(t, includeAB, defaultIncludeAB)
}
func TestNewRejectsIncludeAndExcludeProjects(t *testing.T) {
local := testDB(t)
_, err := New(
"postgres://user:pass@127.0.0.1:1/db?sslmode=disable",
"agentsview",
local,
"test-machine",
true,
SyncOptions{
Projects: []string{"alpha"},
ExcludeProjects: []string{"beta"},
},
)
require.Error(t, err)
assert.Contains(t, err.Error(),
"projects and exclude_projects are mutually exclusive")
}
func TestReadLastPushAtUsesProjectFilterScope(t *testing.T) {
local := testDB(t)
require.NoError(t, local.SetSyncState(
"last_push_at:work",
"2026-03-11T12:00:00.000Z",
))
filterScope := pushSyncStateScope(
"work",
[]string{"alpha", "beta"},
nil,
)
require.NoError(t, local.SetSyncState(
"last_push_at:"+filterScope,
"2026-03-11T13:00:00.000Z",
))
got, err := ReadLastPushAt(
local,
"work",
[]string{"beta", "alpha"},
nil,
true,
)
require.NoError(t, err)
assert.Equal(t, "2026-03-11T13:00:00.000Z", got)
}
func TestReadLastPushAtDoesNotMigrateLegacyStateForProjectFilter(t *testing.T) {
local := testDB(t)
require.NoError(t, local.SetSyncState(
"last_push_at",
"2026-03-11T12:00:00.000Z",
))
got, err := ReadLastPushAt(
local,
"",
[]string{"alpha"},
nil,
true,
)
require.NoError(t, err)
assert.Empty(t, got)
legacyValue, err := local.GetSyncState("last_push_at")
require.NoError(t, err)
assert.Equal(t, "2026-03-11T12:00:00.000Z", legacyValue)
}