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

1773 lines
47 KiB
Go

package postgres
import (
"context"
"database/sql"
"database/sql/driver"
"encoding/json"
"errors"
"io"
"path/filepath"
"strings"
"sync"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.kenn.io/agentsview/internal/db"
)
type syncStateReaderStub struct {
value string
err error
}
func (s syncStateReaderStub) GetSyncState(
key string,
) (string, error) {
return s.value, s.err
}
func (s syncStateReaderStub) SetSyncState(
string, string,
) error {
return nil
}
func (s syncStateReaderStub) GetOrCreateSyncState(
key, defaultValue string,
) (string, error) {
if s.value != "" || s.err != nil {
return s.value, s.err
}
return defaultValue, nil
}
type syncStateStoreStub struct {
values map[string]string
createValue string
}
func (s *syncStateStoreStub) GetSyncState(
key string,
) (string, error) {
return s.values[key], nil
}
func (s *syncStateStoreStub) SetSyncState(
key, value string,
) error {
if s.values == nil {
s.values = make(map[string]string)
}
s.values[key] = value
return nil
}
func (s *syncStateStoreStub) GetOrCreateSyncState(
key, defaultValue string,
) (string, error) {
if s.values == nil {
s.values = make(map[string]string)
}
if value := s.values[key]; value != "" {
return value, nil
}
if s.createValue != "" {
s.values[key] = s.createValue
return s.createValue, nil
}
s.values[key] = defaultValue
return defaultValue, nil
}
type pushAliasRoutingDriver struct{}
type pushAliasRoutingConn struct{}
type pushAliasRoutingTx struct{}
type pushAliasRoutingRows struct {
columns []string
values [][]driver.Value
next int
}
var pushAliasRoutingRegisterOnce sync.Once
func newPushAliasRoutingDB(t *testing.T) *sql.DB {
t.Helper()
pushAliasRoutingRegisterOnce.Do(func() {
sql.Register("agentsview_push_alias_routing", pushAliasRoutingDriver{})
})
pg, err := sql.Open("agentsview_push_alias_routing", t.Name())
require.NoError(t, err, "open push-alias-routing db")
t.Cleanup(func() { _ = pg.Close() })
return pg
}
func (pushAliasRoutingDriver) Open(string) (driver.Conn, error) {
return &pushAliasRoutingConn{}, nil
}
func (c *pushAliasRoutingConn) Prepare(string) (driver.Stmt, error) {
return nil, errors.New("prepare not implemented")
}
func (c *pushAliasRoutingConn) Close() error { return nil }
func (c *pushAliasRoutingConn) Begin() (driver.Tx, error) {
return c.BeginTx(context.Background(), driver.TxOptions{})
}
func (c *pushAliasRoutingConn) BeginTx(
context.Context, driver.TxOptions,
) (driver.Tx, error) {
return pushAliasRoutingTx{}, nil
}
func (c *pushAliasRoutingConn) CheckNamedValue(
*driver.NamedValue,
) error {
return nil
}
func (c *pushAliasRoutingConn) ExecContext(
_ context.Context, query string, _ []driver.NamedValue,
) (driver.Result, error) {
normalized := strings.ToLower(query)
switch {
case strings.Contains(normalized, "insert into model_pricing"):
return driver.RowsAffected(1), nil
case strings.Contains(normalized, "insert into sync_metadata"):
return driver.RowsAffected(1), nil
default:
return driver.RowsAffected(1), nil
}
}
func (c *pushAliasRoutingConn) QueryContext(
_ context.Context, query string, _ []driver.NamedValue,
) (driver.Rows, error) {
normalized := strings.ToLower(query)
switch {
case strings.Contains(normalized, "select coalesce(max(data_version), 0) from sessions"):
return &pushAliasRoutingRows{
columns: []string{"coalesce"},
values: [][]driver.Value{{0}},
}, nil
case strings.Contains(normalized, "from information_schema.tables"):
return &pushAliasRoutingRows{
columns: []string{"exists"},
values: [][]driver.Value{{1}},
}, nil
case strings.Contains(normalized, "from pg_indexes"):
return &pushAliasRoutingRows{
columns: []string{"exists"},
values: [][]driver.Value{{1}},
}, nil
case strings.Contains(normalized, "select exists ("):
return &pushAliasRoutingRows{
columns: []string{"exists"},
values: [][]driver.Value{{false}},
}, nil
case strings.Contains(normalized, "select value from sync_metadata where key = $1"):
return &pushAliasRoutingRows{
columns: []string{"value"},
}, nil
case strings.Contains(normalized, "limit 0"):
return &pushAliasRoutingRows{
columns: []string{"probe"},
}, nil
case strings.Contains(normalized, "select model_pattern, input_per_mtok"):
return &pushAliasRoutingRows{
columns: []string{
"model_pattern",
"input_per_mtok",
"output_per_mtok",
"cache_creation_per_mtok",
"cache_read_per_mtok",
"updated_at",
},
}, nil
case strings.Contains(normalized, "select id from excluded_sessions"):
return &pushAliasRoutingRows{
columns: []string{"id"},
}, nil
default:
return &pushAliasRoutingRows{
columns: []string{"probe"},
}, nil
}
}
func (pushAliasRoutingTx) Commit() error { return nil }
func (pushAliasRoutingTx) Rollback() error { return nil }
func (r *pushAliasRoutingRows) Columns() []string { return r.columns }
func (r *pushAliasRoutingRows) Close() error { return nil }
func (r *pushAliasRoutingRows) Next(dest []driver.Value) error {
if r.next >= len(r.values) {
return io.EOF
}
copy(dest, r.values[r.next])
r.next++
return nil
}
func TestPushMarkerIDReturnsInsertWinner(t *testing.T) {
local, err := db.Open(filepath.Join(t.TempDir(), "local.db"))
require.NoError(t, err, "db.Open")
defer local.Close()
require.NoError(t, local.SetSyncState(pushMarkerIDStateKey, "winner-marker"))
sync := &Sync{local: local}
got, err := sync.pushMarkerID()
require.NoError(t, err, "pushMarkerID")
assert.Equal(t, "winner-marker", got)
stored, err := local.GetSyncState(pushMarkerIDStateKey)
require.NoError(t, err, "GetSyncState")
assert.Equal(t, "winner-marker", stored)
}
func TestPushMarkerIDUsesUnscopedStateAcrossNamedTargets(t *testing.T) {
local, err := db.Open(filepath.Join(t.TempDir(), "local.db"))
require.NoError(t, err, "db.Open")
defer local.Close()
workSync := &Sync{
local: local,
syncState: newScopedSyncStateStore(local, "work", true),
}
archiveSync := &Sync{
local: local,
syncState: newScopedSyncStateStore(local, "archive", false),
}
workMarker, err := workSync.pushMarkerID()
require.NoError(t, err, "work pushMarkerID")
archiveMarker, err := archiveSync.pushMarkerID()
require.NoError(t, err, "archive pushMarkerID")
assert.Equal(t, workMarker, archiveMarker)
stored, err := local.GetSyncState(pushMarkerIDStateKey)
require.NoError(t, err, "GetSyncState")
assert.Equal(t, workMarker, stored)
for _, key := range []string{
pushMarkerIDStateKey + ":work",
pushMarkerIDStateKey + ":archive",
} {
value, err := local.GetSyncState(key)
require.NoError(t, err, "GetSyncState %s", key)
assert.Empty(t, value)
}
}
func TestSessionAliasBackfillForcesOneFullPush(t *testing.T) {
store := &syncStateStoreStub{}
full, needed, err := applySessionAliasBackfillRequirement(
store, false,
)
require.NoError(t, err)
assert.True(t, full, "missing alias backfill marker should force full push")
assert.True(t, needed)
require.NoError(t, markSessionAliasBackfillDone(store))
full, needed, err = applySessionAliasBackfillRequirement(
store, false,
)
require.NoError(t, err)
assert.False(t, full,
"completed alias backfill should preserve incremental push")
assert.False(t, needed)
full, needed, err = applySessionAliasBackfillRequirement(
store, true,
)
require.NoError(t, err)
assert.True(t, full, "explicit full push should stay full")
assert.False(t, needed)
}
func TestTranscriptRevisionBackfillForcesOneFullPush(t *testing.T) {
store := &syncStateStoreStub{}
full, needed, err := applyTranscriptRevisionBackfillRequirement(
store, false,
)
require.NoError(t, err)
assert.True(t, full)
assert.True(t, needed)
require.NoError(t, markTranscriptRevisionBackfillDone(store))
full, needed, err = applyTranscriptRevisionBackfillRequirement(
store, false,
)
require.NoError(t, err)
assert.False(t, full)
assert.False(t, needed)
}
func TestCompleteSessionAliasBackfillMarksDoneUnlessErrors(t *testing.T) {
for _, tc := range []struct {
name string
res PushResult
want string
}{
{name: "clean", want: "1"},
{name: "errors", res: PushResult{Errors: 1}},
// Skipped ownership conflicts are other machines' sessions this host
// can never push; they must not block the one-time backfill marker,
// or a shared hub can never leave the forced-full-push state.
{name: "skipped conflicts", res: PushResult{SkippedConflicts: 1}, want: "1"},
{
name: "errors with skipped conflicts",
res: PushResult{Errors: 1, SkippedConflicts: 2},
},
} {
t.Run(tc.name, func(t *testing.T) {
store := &syncStateStoreStub{}
err := completeSessionAliasBackfill(
store, true, tc.res,
)
require.NoError(t, err)
assert.Equal(t, tc.want,
store.values[sessionAliasBackfillStateKey])
})
}
}
func TestSessionAliasBackfillRequirementUsesSyncAliasStateAcrossFilters(t *testing.T) {
filterScopeA := pushSyncStateScope(
"work",
[]string{"alpha"},
nil,
)
filterScopeB := pushSyncStateScope(
"work",
[]string{"beta"},
nil,
)
store := &syncStateStoreStub{}
syncA := &Sync{
syncState: newScopedSyncStateStore(store, filterScopeA, false),
aliasBackfillState: newScopedSyncStateStore(store, "work", false),
}
syncB := &Sync{
syncState: newScopedSyncStateStore(store, filterScopeB, false),
aliasBackfillState: newScopedSyncStateStore(store, "work", false),
}
full, needed, err := applySessionAliasBackfillRequirement(
syncA.aliasBackfillSyncStateOrDefault(), false,
)
require.NoError(t, err)
assert.True(t, full)
assert.True(t, needed)
require.NoError(t, completeSessionAliasBackfill(
syncA.aliasBackfillSyncStateOrDefault(),
true,
PushResult{},
))
full, needed, err = applySessionAliasBackfillRequirement(
syncB.aliasBackfillSyncStateOrDefault(), false,
)
require.NoError(t, err)
assert.False(t, full, "head behavior: target scope keeps marker across filters")
assert.False(t, needed, "head behavior: marker should not re-arm full push")
assert.Empty(t, store.values[sessionAliasBackfillStateKey+":"+filterScopeA])
assert.Empty(t, store.values[sessionAliasBackfillStateKey+":"+filterScopeB])
assert.Equal(t, "1", store.values[sessionAliasBackfillStateKey+":work"])
}
func TestPushUsesTargetScopedAliasBackfillStateAcrossFilters(t *testing.T) {
filterScopeA := pushSyncStateScope("work", []string{"alpha"}, nil)
filterScopeB := pushSyncStateScope("work", []string{"beta"}, nil)
local := testDB(t)
pg := newPushAliasRoutingDB(t)
ctx := context.Background()
syncA := &Sync{
pg: pg,
local: local,
syncState: newScopedSyncStateStore(local, filterScopeA, false),
aliasBackfillState: newScopedSyncStateStore(local, "work", false),
machine: "push-machine",
schema: "agentsview",
targetFingerprint: "target-fp",
syncStateTarget: filterScopeA,
projects: []string{"alpha"},
schemaDone: true,
}
syncB := &Sync{
pg: pg,
local: local,
syncState: newScopedSyncStateStore(local, filterScopeB, false),
aliasBackfillState: newScopedSyncStateStore(local, "work", false),
machine: "push-machine",
schema: "agentsview",
targetFingerprint: "target-fp",
syncStateTarget: filterScopeB,
projects: []string{"beta"},
schemaDone: true,
}
_, err := syncA.Push(ctx, false, nil)
require.NoError(t, err)
_, err = syncB.Push(ctx, false, nil)
require.NoError(t, err)
targetMarker, err := local.GetSyncState(
sessionAliasBackfillStateKey + ":work",
)
require.NoError(t, err)
assert.Equal(t, "1", targetMarker)
filterMarkerB, err := local.GetSyncState(
sessionAliasBackfillStateKey + ":" + filterScopeB,
)
require.NoError(t, err)
assert.Empty(t, filterMarkerB)
filteredLastPushA, err := local.GetSyncState("last_push_at:" + filterScopeA)
require.NoError(t, err)
assert.NotEmpty(t, filteredLastPushA)
filteredLastPushB, err := local.GetSyncState("last_push_at:" + filterScopeB)
require.NoError(t, err)
assert.NotEmpty(t, filteredLastPushB)
unscopedLastPush, err := local.GetSyncState("last_push_at:work")
require.NoError(t, err)
assert.Empty(t, unscopedLastPush)
}
func TestSessionAliasBackfillStateFallsBackToEffectiveScope(t *testing.T) {
store := &syncStateStoreStub{}
scope := pushSyncStateScope("work", []string{"alpha"}, nil)
syncer := &Sync{
syncState: newScopedSyncStateStore(store, scope, false),
}
require.NoError(t, markSessionAliasBackfillDone(
syncer.aliasBackfillSyncStateOrDefault(),
))
assert.Equal(t, "1", store.values[sessionAliasBackfillStateKey+":"+scope])
}
func TestSessionAliasBackfillKeysStayFilteredForPushState(t *testing.T) {
filterScopeA := pushSyncStateScope("work", []string{"alpha"}, nil)
filterScopeB := pushSyncStateScope("work", []string{"beta"}, nil)
store := &syncStateStoreStub{}
syncA := &Sync{
syncState: newScopedSyncStateStore(store, filterScopeA, false),
aliasBackfillState: newScopedSyncStateStore(store, "work", false),
}
require.NoError(t, syncA.effectiveSyncState().SetSyncState(
"last_push_at", "2026-03-11T12:00:00.000Z",
))
require.NoError(t, syncA.effectiveSyncState().SetSyncState(
lastPushBoundaryStateKey, `{"cutoff":"2026-03-11T12:00:00.000Z"}`,
))
require.NoError(t, syncA.effectiveSyncState().SetSyncState(
lastPushTargetFingerprintKey, "fp-1",
))
require.NoError(t, markSessionAliasBackfillDone(
syncA.aliasBackfillSyncStateOrDefault(),
))
assert.Equal(
t,
"2026-03-11T12:00:00.000Z",
store.values["last_push_at:"+filterScopeA],
)
assert.Equal(
t,
`{"cutoff":"2026-03-11T12:00:00.000Z"}`,
store.values[lastPushBoundaryStateKey+":"+filterScopeA],
)
assert.Equal(
t,
"fp-1",
store.values[lastPushTargetFingerprintKey+":"+filterScopeA],
)
assert.Empty(t, store.values["last_push_at:"+filterScopeB])
assert.Empty(t, store.values[lastPushBoundaryStateKey+":"+filterScopeB])
assert.Empty(t, store.values[lastPushTargetFingerprintKey+":"+filterScopeB])
assert.Empty(t, store.values[sessionAliasBackfillStateKey+":"+filterScopeA])
assert.Empty(t, store.values[sessionAliasBackfillStateKey+":"+filterScopeB])
assert.Equal(
t,
"1",
store.values[sessionAliasBackfillStateKey+":work"],
)
assert.Empty(t, store.values["last_push_at:work"])
}
func TestReadPushBoundaryStateValidity(t *testing.T) {
const cutoff = "2026-03-11T12:34:56.123Z"
tests := []struct {
name string
raw string
wantValid bool
wantLen int
}{
{
name: "missing state",
raw: "",
wantValid: false,
wantLen: 0,
},
{
name: "bare map without cutoff",
raw: `{"sess-001":"fingerprint"}`,
wantValid: false,
wantLen: 0,
},
{
name: "malformed payload",
raw: `{`,
wantValid: false,
wantLen: 0,
},
{
name: "stale cutoff",
raw: `{"cutoff":"2026-03-11T12:34:56.122Z","fingerprints":{"sess-001":"fingerprint"}}`,
wantValid: false,
wantLen: 0,
},
{
name: "matching cutoff",
raw: `{"cutoff":"2026-03-11T12:34:56.123Z","fingerprints":{"sess-001":"fingerprint"}}`,
wantValid: true,
wantLen: 1,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
_, got, valid, err := readBoundaryAndFingerprints(
syncStateReaderStub{value: tc.raw},
cutoff,
)
require.NoError(t, err)
require.Equal(t, tc.wantValid, valid)
require.Len(t, got, tc.wantLen)
})
}
}
func TestLocalSessionSyncMarkerNormalizesSecondPrecisionTimestamps(t *testing.T) {
startedAt := "2026-03-11T12:34:56Z"
endedAt := "2026-03-11T12:34:56.123Z"
got := localSessionSyncMarker(db.Session{
CreatedAt: "2026-03-11T12:34:55Z",
StartedAt: &startedAt,
EndedAt: &endedAt,
})
require.Equal(t, endedAt, got)
}
func TestPGExcludedSessionIDsQueryUsesSingleArrayParameter(t *testing.T) {
query, args := pgExcludedSessionIDsQuery([]string{
"sess-001",
"sess-002",
"sess-003",
})
assert.Contains(t, query, "id = ANY($1)")
assert.NotContains(t, query, "$2")
require.Len(t, args, 1)
assert.Equal(t,
[]string{"sess-001", "sess-002", "sess-003"},
args[0],
)
}
func TestDeletePGExcludedSessionRowsUsesSingleArrayParameter(t *testing.T) {
execer := &capturePGExec{}
require.NoError(t, deletePGExcludedSessionRows(
context.Background(), execer,
[]string{"sess-001", "sess-002", "sess-003"},
))
assert.Contains(t, execer.query, "DELETE FROM sessions")
assert.Contains(t, execer.query, "id = ANY($1)")
require.Len(t, execer.args, 1)
assert.Equal(t,
[]string{"sess-001", "sess-002", "sess-003"},
execer.args[0],
)
}
type capturePGExec struct {
query string
args []any
}
func (c *capturePGExec) ExecContext(
_ context.Context, query string, args ...any,
) (sql.Result, error) {
c.query = query
c.args = args
return driver.RowsAffected(0), nil
}
func TestPushSessionRechecksExclusionAfterSuccessfulUpsert(t *testing.T) {
state := &pushSessionProbeState{
existingExcluded: map[string]bool{
"sess-race": true,
},
}
pg := newPushSessionProbeDB(t, state)
tx, err := pg.BeginTx(context.Background(), nil)
require.NoError(t, err, "BeginTx")
syncer := &Sync{machine: "push-machine"}
err = syncer.pushSession(
context.Background(), tx,
db.Session{
ID: "sess-race",
Project: "proj",
Machine: "push-machine",
Agent: "claude",
CreatedAt: "2026-01-01T00:00:00Z",
},
"marker", nil,
)
require.ErrorIs(t, err, errSessionExcluded)
assert.Equal(t, 1, state.upserts)
assert.Equal(t, 1, state.exclusionChecks)
assert.True(t, state.deletedExcluded,
"excluded row should be deleted after the tombstone is observed")
require.NoError(t, tx.Rollback(), "Rollback")
}
func TestPushSessionStoresVibeFallbackAlias(t *testing.T) {
state := &pushSessionProbeState{aliases: map[string]string{}}
pg := newPushSessionProbeDB(t, state)
tx, err := pg.BeginTx(context.Background(), nil)
require.NoError(t, err, "BeginTx")
sessionDir := filepath.Join(
t.TempDir(),
"session_20260616_083518_abc123",
)
filePath := filepath.Join(sessionDir, "messages.jsonl")
syncer := &Sync{machine: "push-machine"}
err = syncer.pushSession(
context.Background(), tx,
db.Session{
ID: "vibe:canonical-uuid",
Project: "proj",
Machine: "push-machine",
Agent: "vibe",
CreatedAt: "2026-01-01T00:00:00Z",
FilePath: &filePath,
},
"marker", nil,
)
require.NoError(t, err, "pushSession")
assert.Equal(t,
"vibe:session_20260616_083518_abc123",
state.aliases["vibe:canonical-uuid"],
)
require.NoError(t, tx.Rollback(), "Rollback")
}
func TestPushSessionExcludesVibeFallbackAliasWhenCanonicalExcluded(t *testing.T) {
state := &pushSessionProbeState{
existingExcluded: map[string]bool{
"vibe:canonical-deleted": true,
},
excludedIDs: map[string]bool{},
}
pg := newPushSessionProbeDB(t, state)
tx, err := pg.BeginTx(context.Background(), nil)
require.NoError(t, err, "BeginTx")
sessionDir := filepath.Join(
t.TempDir(),
"session_20260616_083518_def456",
)
filePath := filepath.Join(sessionDir, "messages.jsonl")
syncer := &Sync{machine: "push-machine"}
err = syncer.pushSession(
context.Background(), tx,
db.Session{
ID: "vibe:canonical-deleted",
Project: "proj",
Machine: "push-machine",
Agent: "vibe",
CreatedAt: "2026-01-01T00:00:00Z",
FilePath: &filePath,
},
"marker", nil,
)
require.ErrorIs(t, err, errSessionExcluded)
assert.True(t,
state.excludedIDs["vibe:session_20260616_083518_def456"],
"excluded canonical Vibe pushes should tombstone the fallback alias",
)
require.NoError(t, tx.Rollback(), "Rollback")
}
func TestPushSessionSkipsVibeCanonicalWhenFallbackAliasExcluded(t *testing.T) {
state := &pushSessionProbeState{
existingExcluded: map[string]bool{
"vibe:session_20260616_083518_ghi789": true,
},
excludedIDs: map[string]bool{},
}
pg := newPushSessionProbeDB(t, state)
tx, err := pg.BeginTx(context.Background(), nil)
require.NoError(t, err, "BeginTx")
sessionDir := filepath.Join(
t.TempDir(),
"session_20260616_083518_ghi789",
)
filePath := filepath.Join(sessionDir, "messages.jsonl")
syncer := &Sync{machine: "push-machine"}
err = syncer.pushSession(
context.Background(), tx,
db.Session{
ID: "vibe:canonical-active",
Project: "proj",
Machine: "push-machine",
Agent: "vibe",
CreatedAt: "2026-01-01T00:00:00Z",
FilePath: &filePath,
},
"marker", nil,
)
require.ErrorIs(t, err, errSessionExcluded)
assert.True(t, state.excludedIDs["vibe:canonical-active"])
assert.True(t,
state.excludedIDs["vibe:session_20260616_083518_ghi789"],
)
assert.True(t, state.deletedExcluded,
"all excluded aliases should be purged from PG sessions")
require.NoError(t, tx.Rollback(), "Rollback")
}
func TestPurgePGExcludedPushSessionsChecksDerivedAliases(t *testing.T) {
state := &pushSessionProbeState{
existingExcluded: map[string]bool{
"vibe:session_20260616_083518_jkl012": true,
},
excludedIDs: map[string]bool{},
}
pg := newPushSessionProbeDB(t, state)
sessionDir := filepath.Join(
t.TempDir(),
"session_20260616_083518_jkl012",
)
filePath := filepath.Join(sessionDir, "messages.jsonl")
sessionByID := map[string]db.Session{
"vibe:canonical-unchanged": {
ID: "vibe:canonical-unchanged",
Project: "proj",
Machine: "push-machine",
Agent: "vibe",
CreatedAt: "2026-01-01T00:00:00Z",
FilePath: &filePath,
},
}
err := purgePGExcludedPushSessions(
context.Background(), pg, sessionByID,
)
require.NoError(t, err, "purgePGExcludedPushSessions")
assert.Empty(t, sessionByID)
assert.True(t, state.excludedIDs["vibe:canonical-unchanged"])
assert.True(t,
state.excludedIDs["vibe:session_20260616_083518_jkl012"],
)
assert.True(t, state.deletedExcluded,
"all excluded aliases should be purged before fingerprint pruning")
assert.Equal(t, 1, state.exclusionChecks)
assert.Equal(t, 0, state.upserts)
}
type pushSessionProbeDriver struct{}
type pushSessionProbeConn struct {
state *pushSessionProbeState
}
type pushSessionProbeTx struct{}
type pushSessionProbeRows struct {
columns []string
values [][]driver.Value
next int
}
type pushSessionProbeState struct {
mu sync.Mutex
excludedAfterUpsert bool
upserts int
exclusionChecks int
deletedExcluded bool
aliases map[string]string
excludedIDs map[string]bool
existingExcluded map[string]bool
}
var (
pushSessionProbeRegisterOnce sync.Once
pushSessionProbeStatesMu sync.Mutex
pushSessionProbeStates = map[string]*pushSessionProbeState{}
)
func newPushSessionProbeDB(
t *testing.T, state *pushSessionProbeState,
) *sql.DB {
t.Helper()
pushSessionProbeRegisterOnce.Do(func() {
sql.Register("agentsview_push_session_probe", pushSessionProbeDriver{})
})
name := t.Name()
pushSessionProbeStatesMu.Lock()
pushSessionProbeStates[name] = state
pushSessionProbeStatesMu.Unlock()
t.Cleanup(func() {
pushSessionProbeStatesMu.Lock()
delete(pushSessionProbeStates, name)
pushSessionProbeStatesMu.Unlock()
})
pg, err := sql.Open("agentsview_push_session_probe", name)
require.NoError(t, err, "open push-session probe db")
t.Cleanup(func() { _ = pg.Close() })
return pg
}
func (pushSessionProbeDriver) Open(name string) (driver.Conn, error) {
pushSessionProbeStatesMu.Lock()
state := pushSessionProbeStates[name]
pushSessionProbeStatesMu.Unlock()
return &pushSessionProbeConn{state: state}, nil
}
func (c *pushSessionProbeConn) Prepare(string) (driver.Stmt, error) {
return nil, errors.New("prepare not implemented")
}
func (c *pushSessionProbeConn) Close() error { return nil }
func (c *pushSessionProbeConn) Begin() (driver.Tx, error) {
return c.BeginTx(context.Background(), driver.TxOptions{})
}
func (c *pushSessionProbeConn) BeginTx(
context.Context, driver.TxOptions,
) (driver.Tx, error) {
return pushSessionProbeTx{}, nil
}
func (c *pushSessionProbeConn) CheckNamedValue(
*driver.NamedValue,
) error {
return nil
}
func (c *pushSessionProbeConn) ExecContext(
_ context.Context, query string, args []driver.NamedValue,
) (driver.Result, error) {
normalized := strings.ToLower(query)
c.state.mu.Lock()
defer c.state.mu.Unlock()
switch {
case strings.Contains(normalized, "insert into sessions"):
c.state.upserts++
return driver.RowsAffected(1), nil
case strings.Contains(normalized, "delete from sessions") &&
strings.Contains(normalized, "id = any($1)"):
c.state.deletedExcluded = true
return driver.RowsAffected(1), nil
case strings.Contains(normalized, "delete from session_aliases"):
if c.state.aliases != nil && len(args) > 0 {
if sessionID, ok := args[0].Value.(string); ok {
delete(c.state.aliases, sessionID)
}
}
return driver.RowsAffected(1), nil
case strings.Contains(normalized, "insert into session_aliases"):
if c.state.aliases != nil && len(args) > 1 {
sessionID, sessionOK := args[0].Value.(string)
aliasID, aliasOK := args[1].Value.(string)
if sessionOK && aliasOK {
c.state.aliases[sessionID] = aliasID
}
}
return driver.RowsAffected(1), nil
case strings.Contains(normalized, "insert into excluded_sessions"):
if c.state.excludedIDs != nil && len(args) > 0 {
switch ids := args[0].Value.(type) {
case []string:
for _, id := range ids {
c.state.excludedIDs[id] = true
}
case string:
c.state.excludedIDs[ids] = true
}
}
return driver.RowsAffected(1), nil
default:
return nil, errors.New("unexpected push-session probe exec")
}
}
func (c *pushSessionProbeConn) QueryContext(
_ context.Context, query string, args []driver.NamedValue,
) (driver.Rows, error) {
normalized := strings.ToLower(query)
c.state.mu.Lock()
defer c.state.mu.Unlock()
switch {
case strings.Contains(normalized, "select machine, owner_marker"):
return &pushSessionProbeRows{
columns: []string{"machine", "owner_marker"},
}, nil
case strings.Contains(normalized, "select id") &&
strings.Contains(normalized, "excluded_sessions") &&
strings.Contains(normalized, "id = any($1)"):
c.state.exclusionChecks++
values := [][]driver.Value{}
for _, id := range namedValueStrings(args) {
if c.state.existingExcluded[id] {
values = append(values, []driver.Value{id})
}
}
return &pushSessionProbeRows{
columns: []string{"id"},
values: values,
}, nil
case strings.Contains(normalized, "select exists") &&
strings.Contains(normalized, "excluded_sessions"):
c.state.exclusionChecks++
excluded := c.state.excludedAfterUpsert
if c.state.existingExcluded != nil && len(args) > 0 {
id, _ := args[0].Value.(string)
excluded = c.state.existingExcluded[id]
}
return &pushSessionProbeRows{
columns: []string{"exists"},
values: [][]driver.Value{
{excluded},
},
}, nil
default:
return nil, errors.New("unexpected push-session probe query")
}
}
func (pushSessionProbeTx) Commit() error { return nil }
func (pushSessionProbeTx) Rollback() error { return nil }
func (r *pushSessionProbeRows) Columns() []string { return r.columns }
func (r *pushSessionProbeRows) Close() error { return nil }
func (r *pushSessionProbeRows) Next(dest []driver.Value) error {
if r.next >= len(r.values) {
return io.EOF
}
copy(dest, r.values[r.next])
r.next++
return nil
}
func TestSessionPushFingerprintDiffers(t *testing.T) {
base := db.Session{
ID: "sess-001",
Project: "proj",
Machine: "laptop",
Agent: "claude",
MessageCount: 5,
UserMessageCount: 2,
CreatedAt: "2026-03-11T12:00:00Z",
}
fp1 := sessionPushFingerprint(base, base.Machine, "", "", "")
tests := []struct {
name string
modify func(s db.Session) db.Session
}{
{
name: "message count change",
modify: func(s db.Session) db.Session {
s.MessageCount = 6
return s
},
},
{
name: "display name change",
modify: func(s db.Session) db.Session {
name := "new name"
s.DisplayName = &name
return s
},
},
{
name: "session_name change",
modify: func(s db.Session) db.Session {
n := "agent-provided-title"
s.SessionName = &n
return s
},
},
{
name: "ended at change",
modify: func(s db.Session) db.Session {
ended := "2026-03-11T13:00:00Z"
s.EndedAt = &ended
return s
},
},
{
name: "file hash change",
modify: func(s db.Session) db.Session {
hash := "abc123"
s.FileHash = &hash
return s
},
},
{
name: "file path change",
modify: func(s db.Session) db.Session {
path := "/home/test/.vibe/sessions/alias.jsonl"
s.FilePath = &path
return s
},
},
{
name: "termination_status change",
modify: func(s db.Session) db.Session {
ts := "tool_call_pending"
s.TerminationStatus = &ts
return s
},
},
{
name: "automated classification change",
modify: func(s db.Session) db.Session {
s.IsAutomated = true
return s
},
},
{
name: "quality signal version change",
modify: func(s db.Session) db.Session {
s.QualitySignalVersion = db.CurrentQualitySignalVersion
return s
},
},
{
name: "quality signal count change",
modify: func(s db.Session) db.Session {
s.QualitySignalVersion = db.CurrentQualitySignalVersion
s.DuplicatePromptCount = 1
return s
},
},
{
name: "quality signal boolean change",
modify: func(s db.Session) db.Session {
s.QualitySignalVersion = db.CurrentQualitySignalVersion
s.UnstructuredStart = true
return s
},
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
modified := tc.modify(base)
fp2 := sessionPushFingerprint(modified, modified.Machine, "", "", "")
require.NotEqual(t, fp1, fp2,
"fingerprint should differ after %s", tc.name)
})
}
assert.Equal(t, fp1, sessionPushFingerprint(base, base.Machine, "", "", ""),
"identical sessions should produce identical fingerprints")
}
func TestSessionPushFingerprintIgnoresVolatileStatFields(t *testing.T) {
hash := "content-hash"
localModifiedAt := "2026-03-11T12:00:00.000Z"
fileMtime := int64(1700000000000000000)
base := db.Session{
ID: "sess-001",
Project: "proj",
Machine: "laptop",
Agent: "claude",
MessageCount: 5,
UserMessageCount: 2,
FileHash: &hash,
FileMtime: &fileMtime,
LocalModifiedAt: &localModifiedAt,
CreatedAt: "2026-03-11T12:00:00Z",
}
baseFP := sessionPushFingerprint(base, base.Machine, "", "", "deps")
statOnlyMtime := int64(1700000001000000000)
statOnlyModifiedAt := "2026-03-11T12:00:01.000Z"
statOnly := base
statOnly.FileMtime = &statOnlyMtime
statOnly.LocalModifiedAt = &statOnlyModifiedAt
assert.Equal(t, baseFP, sessionPushFingerprint(statOnly, statOnly.Machine, "", "", "deps"),
"file stat churn should not change push candidacy")
contentChanged := statOnly
contentChanged.MessageCount++
assert.NotEqual(t, baseFP,
sessionPushFingerprint(contentChanged, contentChanged.Machine, "", "", "deps"),
"content changes should still change push candidacy")
assert.NotEqual(t, baseFP,
sessionPushFingerprint(statOnly, statOnly.Machine, "", "", "changed-deps"),
"dependent row changes should still change push candidacy")
}
func TestLocalSessionDependencyPushFingerprintTracksMessageEditsWithoutFileHash(
t *testing.T,
) {
localDB := testDB(t)
const sessID = "sess-message-edit"
require.NoError(t, localDB.UpsertSession(db.Session{
ID: sessID,
Project: "proj",
Machine: "laptop",
Agent: "claude",
MessageCount: 1,
UserMessageCount: 1,
CreatedAt: "2026-03-11T12:00:00Z",
}))
require.NoError(t, localDB.InsertMessages([]db.Message{{
SessionID: sessID,
Ordinal: 0,
Role: "user",
Content: "before",
}}))
depsBefore, err := localSessionDependencyPushFingerprint(
context.Background(), localDB, sessID, "", true,
)
require.NoError(t, err)
session := db.Session{
ID: sessID,
Project: "proj",
Machine: "laptop",
Agent: "claude",
MessageCount: 1,
UserMessageCount: 1,
CreatedAt: "2026-03-11T12:00:00Z",
}
fpBefore := sessionPushFingerprint(
session, session.Machine, "", "", depsBefore,
)
require.NoError(t, localDB.ReplaceSessionMessages(sessID, []db.Message{{
SessionID: sessID,
Ordinal: 0,
Role: "user",
Content: "after",
}}))
depsAfter, err := localSessionDependencyPushFingerprint(
context.Background(), localDB, sessID, "", true,
)
require.NoError(t, err)
fpAfter := sessionPushFingerprint(
session, session.Machine, "", "", depsAfter,
)
assert.NotEqual(t, depsBefore, depsAfter)
assert.NotEqual(t, fpBefore, fpAfter,
"same-count message edits should remain push candidates without file_hash")
}
func TestSessionPushFingerprintIncludesUsageEventFingerprint(
t *testing.T,
) {
base := db.Session{
ID: "sess-001",
Project: "proj",
Machine: "laptop",
Agent: "claude",
MessageCount: 5,
UserMessageCount: 2,
CreatedAt: "2026-03-11T12:00:00Z",
}
withoutUsage := sessionPushFingerprint(base, base.Machine, "", "", "")
withUsage := sessionPushFingerprint(base, base.Machine, "usage-fp", "", "")
assert.NotEqual(t, withoutUsage, withUsage,
"usage event fingerprint should affect session fingerprint")
}
func TestSessionPushFingerprintTracksResolvedMachine(t *testing.T) {
sentinel := db.Session{
ID: "sess-001",
Project: "proj",
Machine: "local",
Agent: "claude",
CreatedAt: "2026-03-11T12:00:00Z",
}
fpA := sessionPushFingerprint(
sentinel, pushedSessionMachine(sentinel, "host-a"), "", "", "")
fpB := sessionPushFingerprint(
sentinel, pushedSessionMachine(sentinel, "host-b"), "", "", "")
assert.NotEqual(t, fpA, fpB,
"sentinel session fingerprint must change with the fallback machine")
real := db.Session{
ID: "sess-002",
Project: "proj",
Machine: "real-host",
Agent: "claude",
CreatedAt: "2026-03-11T12:00:00Z",
}
fp1 := sessionPushFingerprint(
real, pushedSessionMachine(real, "host-a"), "", "", "")
fp2 := sessionPushFingerprint(
real, pushedSessionMachine(real, "host-b"), "", "", "")
assert.Equal(t, fp1, fp2,
"a session with a real machine ignores the fallback")
}
func TestPushedSessionMachine(t *testing.T) {
tests := []struct {
name string
session db.Session
fallback string
want string
}{
{
name: "preserves source machine",
session: db.Session{
Machine: "remote-host",
},
fallback: "push-host",
want: "remote-host",
},
{
name: "falls back for empty machine",
session: db.Session{},
fallback: "push-host",
want: "push-host",
},
{
name: "falls back for local sentinel",
session: db.Session{
Machine: "local",
},
fallback: "push-host",
want: "push-host",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.want,
pushedSessionMachine(tc.session, tc.fallback))
})
}
}
func TestSessionPushFingerprintNoFieldCollisions(
t *testing.T,
) {
s1 := db.Session{
ID: "ab",
Project: "cd",
CreatedAt: "2026-03-11T12:00:00Z",
}
s2 := db.Session{
ID: "a",
Project: "bcd",
CreatedAt: "2026-03-11T12:00:00Z",
}
assert.NotEqual(t,
sessionPushFingerprint(s1, s1.Machine, "", "", ""),
sessionPushFingerprint(s2, s2.Machine, "", "", ""),
"length-prefixed fingerprints should not collide")
}
func TestLocalMessageRoleTimePGFingerprintNormalizesNanoseconds(
t *testing.T,
) {
localDB, err := db.Open(filepath.Join(t.TempDir(), "local.db"))
require.NoError(t, err, "db.Open")
defer localDB.Close()
const sessID = "pg-role-time-nanos"
require.NoError(t, localDB.UpsertSession(db.Session{
ID: sessID,
Project: "proj",
Machine: "host",
Agent: "shelley",
CreatedAt: "2026-03-11T12:34:56Z",
}), "UpsertSession")
require.NoError(t, localDB.InsertMessages([]db.Message{{
SessionID: sessID,
Ordinal: 1,
Role: "assistant",
Content: "answer",
ContentLength: len("answer"),
Timestamp: "2026-03-11T12:34:56.123456789Z",
}}), "InsertMessages")
got, err := localMessageRoleTimePGFingerprint(localDB, sessID)
require.NoError(t, err)
assert.Equal(t,
"1|9:assistant|27:2026-03-11T12:34:56.123456Z;",
got)
raw, err := localDB.MessageRoleTimeFingerprint(sessID)
require.NoError(t, err)
assert.NotEqual(t, raw, got,
"PG push fingerprint must not use raw nanosecond text")
}
func TestFinalizePushStatePersistsEmptyBoundary(
t *testing.T,
) {
const cutoff = "2026-03-11T12:34:56.123Z"
store := &syncStateStoreStub{}
require.NoError(t, finalizePushState(
store, cutoff, nil, nil, map[string]string{},
))
assert.Equal(t, cutoff, store.values["last_push_at"])
raw := store.values[lastPushBoundaryStateKey]
require.NotEmpty(t, raw, "last_push_boundary_state should be written")
var state pushBoundaryState
require.NoError(t, json.Unmarshal([]byte(raw), &state))
assert.Equal(t, cutoff, state.Cutoff)
assert.Empty(t, state.Fingerprints)
}
func TestFinalizeUnfilteredPushStatePreservesPriorFingerprintsWithoutPushedSessions(
t *testing.T,
) {
const (
lastPush = "2026-03-11T12:00:00.000Z"
cutoff = "2026-03-11T12:34:56.123Z"
)
store := &syncStateStoreStub{}
require.NoError(t, finalizeUnfilteredPushState(
store, lastPush, cutoff, nil,
map[string]string{"sess-001": "fp-001"},
map[string]string{},
0,
))
assert.Equal(t, cutoff, store.values["last_push_at"])
raw := store.values[lastPushBoundaryStateKey]
require.NotEmpty(t, raw, "last_push_boundary_state should be written")
var state pushBoundaryState
require.NoError(t, json.Unmarshal([]byte(raw), &state))
assert.Equal(t, cutoff, state.Cutoff)
assert.Equal(t, "fp-001", state.Fingerprints["sess-001"])
}
func TestFinalizeUnfilteredPushStatePreservesSkippedFingerprintsAfterSuccessfulPush(
t *testing.T,
) {
const (
lastPush = "2026-03-11T12:00:00.000Z"
cutoff = "2026-03-11T12:34:56.123Z"
)
pushed := []db.Session{{
ID: "sess-002",
CreatedAt: "2026-03-11T12:10:00Z",
}}
store := &syncStateStoreStub{}
require.NoError(t, finalizeUnfilteredPushState(
store, lastPush, cutoff, pushed,
map[string]string{"sess-001": "fp-001"},
map[string]string{"sess-002": "fp-002"},
0,
))
assert.Equal(t, cutoff, store.values["last_push_at"])
raw := store.values[lastPushBoundaryStateKey]
require.NotEmpty(t, raw, "last_push_boundary_state should be written")
var state pushBoundaryState
require.NoError(t, json.Unmarshal([]byte(raw), &state))
assert.Equal(t, cutoff, state.Cutoff)
assert.Equal(t, "fp-001", state.Fingerprints["sess-001"])
assert.Equal(t, "fp-002", state.Fingerprints["sess-002"])
}
func TestFinalizeFilteredPushStateAdvancesScopedWatermark(
t *testing.T,
) {
const cutoff = "2026-03-11T12:34:56.123Z"
store := &syncStateStoreStub{}
require.NoError(t, finalizeFilteredPushState(
store, "", cutoff, nil, nil, map[string]string{}, 0,
))
assert.Equal(t, cutoff, store.values["last_push_at"])
raw := store.values[lastPushBoundaryStateKey]
require.NotEmpty(t, raw, "last_push_boundary_state should be written")
var state pushBoundaryState
require.NoError(t, json.Unmarshal([]byte(raw), &state))
assert.Equal(t, cutoff, state.Cutoff)
assert.Empty(t, state.Fingerprints)
}
func TestFinalizeFilteredPushStatePreservesPriorFingerprintsOnSuccess(
t *testing.T,
) {
const cutoff = "2026-03-11T12:34:56.123Z"
store := &syncStateStoreStub{}
require.NoError(t, finalizeFilteredPushState(
store, "", cutoff, nil,
map[string]string{"sess-001": "fp-001"},
map[string]string{},
0,
))
assert.Equal(t, cutoff, store.values["last_push_at"])
raw := store.values[lastPushBoundaryStateKey]
require.NotEmpty(t, raw, "last_push_boundary_state should be written")
var state pushBoundaryState
require.NoError(t, json.Unmarshal([]byte(raw), &state))
assert.Equal(t, cutoff, state.Cutoff)
assert.Equal(t, "fp-001", state.Fingerprints["sess-001"])
}
func TestFinalizeFilteredPushStateKeepsWatermarkOnErrors(
t *testing.T,
) {
const lastPush = "2026-03-11T12:00:00.000Z"
const cutoff = "2026-03-11T12:34:56.123Z"
store := &syncStateStoreStub{}
require.NoError(t, finalizeFilteredPushState(
store, lastPush, cutoff, nil,
map[string]string{"sess-001": "fp-001"},
map[string]string{},
1,
))
assert.Equal(t, lastPush, store.values["last_push_at"])
raw := store.values[lastPushBoundaryStateKey]
require.NotEmpty(t, raw, "last_push_boundary_state should be written")
var state pushBoundaryState
require.NoError(t, json.Unmarshal([]byte(raw), &state))
assert.Equal(t, lastPush, state.Cutoff)
assert.Equal(t, "fp-001", state.Fingerprints["sess-001"])
}
func TestPushTargetState(t *testing.T) {
tests := []struct {
name string
lastPush string
boundary string
stored string
current string
wantReset bool
wantReason string
}{
{
name: "first push has no reset",
stored: "",
current: "v1:new",
wantReset: false,
},
{
name: "missing runtime fingerprint skips reset",
lastPush: "2026-03-11T12:34:56.123Z",
stored: "v1:old",
current: "",
wantReset: false,
},
{
name: "legacy watermark without fingerprint resets",
lastPush: "2026-03-11T12:34:56.123Z",
current: "v1:new",
wantReset: true,
wantReason: "local push state exists without a stored PG target fingerprint",
},
{
name: "legacy filtered boundary without fingerprint resets",
boundary: `{"cutoff":"2026-03-11T12:34:56.123Z","fingerprints":{"sess-001":"fp"}}`,
current: "v1:new",
wantReset: true,
wantReason: "local push state exists without a stored PG target fingerprint",
},
{
name: "changed target resets",
lastPush: "2026-03-11T12:34:56.123Z",
stored: "v1:old",
current: "v1:new",
wantReset: true,
wantReason: "PG target fingerprint changed",
},
{
name: "same target keeps watermark",
lastPush: "2026-03-11T12:34:56.123Z",
stored: "v1:same",
current: "v1:same",
wantReset: false,
},
{
name: "filtered boundary keeps same target state",
boundary: `{"cutoff":"2026-03-11T12:34:56.123Z","fingerprints":{"sess-001":"fp"}}`,
stored: "v1:same",
current: "v1:same",
wantReset: false,
},
{
name: "filtered boundary resets on target change",
boundary: `{"cutoff":"2026-03-11T12:34:56.123Z","fingerprints":{"sess-001":"fp"}}`,
stored: "v1:old",
current: "v1:new",
wantReset: true,
wantReason: "PG target fingerprint changed",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
gotReset, gotReason := pushTargetState(
tc.lastPush, tc.boundary, tc.stored, tc.current,
)
assert.Equal(t, tc.wantReset, gotReset)
assert.Equal(t, tc.wantReason, gotReason)
})
}
}
func TestFinalizePushStateMergesPriorFingerprints(
t *testing.T,
) {
const cutoff = "2026-03-11T12:34:56.123Z"
priorFingerprints := map[string]string{
"sess-001": "fp-001",
}
cycle2Sessions := []db.Session{
{
ID: "sess-002",
CreatedAt: "2026-03-11T12:00:00Z",
MessageCount: 3,
},
}
store := &syncStateStoreStub{}
require.NoError(t, finalizePushState(
store, cutoff, cycle2Sessions,
priorFingerprints,
map[string]string{"sess-002": sessionPushFingerprint(cycle2Sessions[0], cycle2Sessions[0].Machine, "", "", "")},
))
raw := store.values[lastPushBoundaryStateKey]
require.NotEmpty(t, raw, "last_push_boundary_state should be written")
var state pushBoundaryState
require.NoError(t, json.Unmarshal([]byte(raw), &state))
require.Len(t, state.Fingerprints, 2)
assert.Equal(t, "fp-001", state.Fingerprints["sess-001"])
_, ok := state.Fingerprints["sess-002"]
assert.True(t, ok, "sess-002 fingerprint should be present")
}
func TestSanitizePG(t *testing.T) {
tests := []struct {
name string
input string
want string
}{
{
name: "clean string",
input: "hello world",
want: "hello world",
},
{
name: "null bytes stripped",
input: "hello\x00world",
want: "helloworld",
},
{
name: "multiple null bytes",
input: "\x00a\x00b\x00",
want: "ab",
},
{
name: "truncated 3-byte sequence",
input: "hello\xe2world",
want: "helloworld",
},
{
name: "truncated 2 of 3 bytes",
input: "hello\xe2\x80world",
want: "helloworld",
},
{
name: "valid multibyte preserved",
// U+2026 HORIZONTAL ELLIPSIS = e2 80 a6
input: "hello\xe2\x80\xa6world",
want: "hello\xe2\x80\xa6world",
},
{
name: "null and invalid combined",
input: "a\x00b\xe2c",
want: "abc",
},
{
name: "empty string",
input: "",
want: "",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
assert.Equal(t, tc.want, sanitizePG(tc.input))
})
}
}
func TestNilIfEmptySanitizes(t *testing.T) {
assert.Equal(t, any("helloworld"), nilIfEmpty("hello\x00world"))
assert.Nil(t, nilIfEmpty(""), "nilIfEmpty(\"\") should be nil")
// A string that reduces to empty after sanitization
// should return nil, not "".
assert.Nil(t, nilIfEmpty("\x00"), "nilIfEmpty(\"\\x00\") should be nil")
}
func TestNilStrSanitizes(t *testing.T) {
s := "hello\xe2world"
assert.Equal(t, any("helloworld"), nilStr(&s))
// A *string that reduces to empty after sanitization
// should return nil.
nul := "\x00"
assert.Nil(t, nilStr(&nul), "nilStr(\"\\x00\") should be nil")
}
func TestShouldSkipSessionMessagesInBatchedPush(t *testing.T) {
const sessionID = "sess-batched"
baseComparisons := &pushMessageComparison{
MessageAggregates: map[string]pushMessageAggregate{
sessionID: {Count: 2, Sum: 12, Max: 6, Min: 1},
},
MessageContentHash: map[string]string{
sessionID: "abc",
},
MessageRoleTime: map[string]string{
sessionID: "role-time",
},
MessageFlags: map[string]string{
sessionID: "flags",
},
MessageSystemOrdinals: map[string]string{
sessionID: "0,1",
},
MessageTokenFingerprint: map[string]string{
sessionID: "tokens",
},
ToolCallAggregates: map[string]pushToolCallAggregate{
sessionID: {Count: 1, Sum: 99},
},
ToolCallFingerprint: map[string]string{
sessionID: "toolcalls",
},
ToolResultFingerprint: map[string]string{
sessionID: "results",
},
UsageEventFingerprint: map[string]string{
sessionID: "usage",
},
}
unchangedFP := pushLocalMessageFingerprint{
Sum: 12,
Max: 6,
Min: 1,
ContentHashFP: "abc",
RoleTimeFP: "role-time",
FlagsFP: "flags",
SystemFP: "0,1",
ToolCallCount: 1,
ToolCallSum: 99,
ToolCallFP: "toolcalls",
ToolResultFP: "results",
TokenFP: "tokens",
UsageEventFP: "usage",
}
assert.True(t, shouldSkipSessionMessages(
sessionID, 2, unchangedFP, false, baseComparisons,
), "unchanged sessions should be skipped as unchanged")
changedFP := unchangedFP
changedFP.ToolCallSum = 100
assert.False(t, shouldSkipSessionMessages(
sessionID, 2, changedFP, false, baseComparisons,
), "tool-call sum mismatch should force push")
changedFP = unchangedFP
changedFP.ToolResultFP = "changed-results"
assert.False(t, shouldSkipSessionMessages(
sessionID, 2, changedFP, false, baseComparisons,
), "tool-result event mismatch should force push")
assert.False(t, shouldSkipSessionMessages(
sessionID, 2, unchangedFP, true, baseComparisons,
), "full mode should not skip by fingerprint check")
}