97ae601cfd
Desktop Client Build / Resolve Build Metadata (push) Successful in 28s
Frontend CI / Frontend (push) Successful in 2m53s
Backend CI / Backend (push) Successful in 16m10s
Desktop Client Build / Build Desktop Client (push) Successful in 23m44s
Desktop Client Build / Publish Client Artifacts to NAS (push) Successful in 50s
336 lines
9.4 KiB
Go
336 lines
9.4 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/geo-platform/tenant-api/internal/shared/auth"
|
|
"github.com/geo-platform/tenant-api/internal/tenant/repository"
|
|
)
|
|
|
|
type desktopAccountRepoSpy struct {
|
|
markDesktopID uuid.UUID
|
|
markWorkspaceID int64
|
|
markUserID int64
|
|
tombstoneActorDesktopID uuid.UUID
|
|
tombstoneActorWorkspaceID int64
|
|
tombstoneActorUserID int64
|
|
}
|
|
|
|
func (r *desktopAccountRepoSpy) ListByClient(context.Context, int64, uuid.UUID) ([]repository.DesktopAccount, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (r *desktopAccountRepoSpy) ListByUser(context.Context, int64, int64) ([]repository.DesktopAccount, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (r *desktopAccountRepoSpy) GetByDesktopID(context.Context, uuid.UUID, int64) (*repository.DesktopAccount, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (r *desktopAccountRepoSpy) GetByIdentity(context.Context, int64, uuid.UUID, string, string) (*repository.DesktopAccount, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (r *desktopAccountRepoSpy) Upsert(context.Context, repository.UpsertDesktopAccountParams) (*repository.DesktopAccount, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (r *desktopAccountRepoSpy) Patch(context.Context, repository.PatchDesktopAccountParams) (*repository.DesktopAccount, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (r *desktopAccountRepoSpy) Tombstone(context.Context, uuid.UUID, int64, uuid.UUID, int64) (*repository.DesktopAccount, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func (r *desktopAccountRepoSpy) TombstoneForActor(_ context.Context, desktopID uuid.UUID, workspaceID, userID int64) (*repository.DesktopAccount, error) {
|
|
r.tombstoneActorDesktopID = desktopID
|
|
r.tombstoneActorWorkspaceID = workspaceID
|
|
r.tombstoneActorUserID = userID
|
|
now := time.Date(2026, 6, 18, 9, 45, 0, 0, time.UTC)
|
|
return &repository.DesktopAccount{
|
|
DesktopID: desktopID,
|
|
TenantID: 10,
|
|
WorkspaceID: workspaceID,
|
|
UserID: userID,
|
|
Platform: "baijiahao",
|
|
PlatformUID: "351884467",
|
|
DisplayName: "Media Account",
|
|
Health: "live",
|
|
DeletedAt: &now,
|
|
}, nil
|
|
}
|
|
|
|
func (r *desktopAccountRepoSpy) MarkDeleteRequested(_ context.Context, desktopID uuid.UUID, workspaceID, userID int64) (*repository.DesktopAccount, error) {
|
|
r.markDesktopID = desktopID
|
|
r.markWorkspaceID = workspaceID
|
|
r.markUserID = userID
|
|
now := time.Date(2026, 6, 18, 9, 30, 0, 0, time.UTC)
|
|
return &repository.DesktopAccount{
|
|
DesktopID: desktopID,
|
|
TenantID: 10,
|
|
WorkspaceID: workspaceID,
|
|
UserID: userID,
|
|
Platform: "toutiaohao",
|
|
PlatformUID: "122707592",
|
|
DisplayName: "Media Account",
|
|
Health: "live",
|
|
DeleteRequestedAt: &now,
|
|
}, nil
|
|
}
|
|
|
|
func (r *desktopAccountRepoSpy) ClearDeleteRequested(context.Context, uuid.UUID, int64, int64) (*repository.DesktopAccount, error) {
|
|
return nil, nil
|
|
}
|
|
|
|
func TestResolveDesktopClientOnline_PresenceHitWins(t *testing.T) {
|
|
now := time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
|
|
|
|
online := resolveDesktopClientOnline(&repository.DesktopClient{
|
|
ID: uuid.New(),
|
|
LastSeenAt: nil,
|
|
}, true, true, now)
|
|
|
|
assert.True(t, online)
|
|
}
|
|
|
|
func TestRequestDeleteScopesToActorUser(t *testing.T) {
|
|
repo := &desktopAccountRepoSpy{}
|
|
service := &DesktopAccountService{repo: repo}
|
|
accountID := uuid.New()
|
|
|
|
view, err := service.RequestDelete(
|
|
context.Background(),
|
|
auth.Actor{UserID: 42, TenantID: 10, PrimaryWorkspaceID: 7},
|
|
accountID,
|
|
false,
|
|
)
|
|
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, accountID, repo.markDesktopID)
|
|
assert.Equal(t, int64(7), repo.markWorkspaceID)
|
|
assert.Equal(t, int64(42), repo.markUserID)
|
|
assert.NotNil(t, view)
|
|
assert.NotNil(t, view.DeleteRequestedAt)
|
|
}
|
|
|
|
func TestResolveDesktopClientOnline_PresenceMissWithKnownPresenceIsOffline(t *testing.T) {
|
|
now := time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
|
|
lastSeen := now.Add(-desktopClientPresenceTTL / 2)
|
|
|
|
online := resolveDesktopClientOnline(&repository.DesktopClient{
|
|
ID: uuid.New(),
|
|
LastSeenAt: &lastSeen,
|
|
}, false, true, now)
|
|
|
|
assert.False(t, online)
|
|
}
|
|
|
|
func TestResolveDesktopClientOnline_FallsBackToRecentHeartbeatWhenPresenceUnknown(t *testing.T) {
|
|
now := time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
|
|
lastSeen := now.Add(-desktopClientPresenceTTL / 2)
|
|
|
|
online := resolveDesktopClientOnline(&repository.DesktopClient{
|
|
ID: uuid.New(),
|
|
LastSeenAt: &lastSeen,
|
|
}, false, false, now)
|
|
|
|
assert.True(t, online)
|
|
}
|
|
|
|
func TestResolveDesktopClientOnline_StaleHeartbeatIsOffline(t *testing.T) {
|
|
now := time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
|
|
lastSeen := now.Add(-(desktopClientPresenceTTL + time.Second))
|
|
|
|
online := resolveDesktopClientOnline(&repository.DesktopClient{
|
|
ID: uuid.New(),
|
|
LastSeenAt: &lastSeen,
|
|
}, false, false, now)
|
|
|
|
assert.False(t, online)
|
|
}
|
|
|
|
func TestBuildDesktopAccountView_StoredClientOwnershipWinsOverPresence(t *testing.T) {
|
|
service := &DesktopAccountService{now: func() time.Time {
|
|
return time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
|
|
}}
|
|
accountID := uuid.New()
|
|
staleClientID := uuid.New()
|
|
activeClientID := uuid.New()
|
|
lastSeen := time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
|
|
deviceName := "Desktop MacIntel"
|
|
|
|
view := service.buildDesktopAccountView(
|
|
&repository.DesktopAccount{
|
|
DesktopID: accountID,
|
|
ClientID: &staleClientID,
|
|
Platform: "toutiaohao",
|
|
PlatformUID: "platform:4181862206",
|
|
DisplayName: "ireader",
|
|
Health: "live",
|
|
},
|
|
map[uuid.UUID]*repository.DesktopClient{
|
|
activeClientID: {
|
|
ID: activeClientID,
|
|
LastSeenAt: &lastSeen,
|
|
DeviceName: &deviceName,
|
|
},
|
|
},
|
|
map[uuid.UUID]uuid.UUID{
|
|
accountID: activeClientID,
|
|
},
|
|
map[uuid.UUID]bool{
|
|
activeClientID: true,
|
|
},
|
|
map[uuid.UUID]bool{
|
|
activeClientID: true,
|
|
},
|
|
)
|
|
|
|
if assert.NotNil(t, view.ClientID) {
|
|
assert.Equal(t, staleClientID.String(), *view.ClientID)
|
|
}
|
|
if assert.NotNil(t, view.ClientOnline) {
|
|
assert.False(t, *view.ClientOnline)
|
|
}
|
|
if assert.NotNil(t, view.AccountSessionOnline) {
|
|
assert.False(t, *view.AccountSessionOnline)
|
|
}
|
|
if assert.NotNil(t, view.TaskConsumerOnline) {
|
|
assert.False(t, *view.TaskConsumerOnline)
|
|
}
|
|
assert.Equal(t, "4181862206", view.PlatformUID)
|
|
assert.Nil(t, view.ClientLastSeenAt)
|
|
assert.Nil(t, view.ClientDeviceName)
|
|
}
|
|
|
|
func TestBuildDesktopAccountView_FallsBackToStoredClientWhenNoPresence(t *testing.T) {
|
|
now := time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
|
|
service := &DesktopAccountService{now: func() time.Time { return now }}
|
|
accountID := uuid.New()
|
|
storedClientID := uuid.New()
|
|
lastSeen := now.Add(-desktopClientPresenceTTL / 2)
|
|
|
|
view := service.buildDesktopAccountView(
|
|
&repository.DesktopAccount{
|
|
DesktopID: accountID,
|
|
ClientID: &storedClientID,
|
|
Platform: "toutiaohao",
|
|
PlatformUID: "4181862206",
|
|
DisplayName: "ireader",
|
|
Health: "live",
|
|
},
|
|
map[uuid.UUID]*repository.DesktopClient{
|
|
storedClientID: {
|
|
ID: storedClientID,
|
|
LastSeenAt: &lastSeen,
|
|
},
|
|
},
|
|
nil,
|
|
nil,
|
|
nil,
|
|
)
|
|
|
|
if assert.NotNil(t, view.ClientID) {
|
|
assert.Equal(t, storedClientID.String(), *view.ClientID)
|
|
}
|
|
if assert.NotNil(t, view.ClientOnline) {
|
|
assert.True(t, *view.ClientOnline)
|
|
}
|
|
assert.Equal(t, &lastSeen, view.ClientLastSeenAt)
|
|
}
|
|
|
|
func TestBuildDesktopAccountView_SplitsHeartbeatAccountSessionAndTaskConsumer(t *testing.T) {
|
|
now := time.Date(2026, 4, 19, 21, 30, 0, 0, time.UTC)
|
|
service := &DesktopAccountService{now: func() time.Time { return now }}
|
|
accountID := uuid.New()
|
|
clientID := uuid.New()
|
|
lastSeen := now.Add(-time.Minute)
|
|
deviceName := "Windows Workstation"
|
|
|
|
view := service.buildDesktopAccountView(
|
|
&repository.DesktopAccount{
|
|
DesktopID: accountID,
|
|
ClientID: &clientID,
|
|
Platform: "sohuhao",
|
|
PlatformUID: "110424528162",
|
|
DisplayName: "全屋定制老炮",
|
|
Health: "live",
|
|
},
|
|
map[uuid.UUID]*repository.DesktopClient{
|
|
clientID: {
|
|
ID: clientID,
|
|
LastSeenAt: &lastSeen,
|
|
DeviceName: &deviceName,
|
|
},
|
|
},
|
|
map[uuid.UUID]uuid.UUID{
|
|
accountID: clientID,
|
|
},
|
|
map[uuid.UUID]bool{
|
|
clientID: true,
|
|
},
|
|
map[uuid.UUID]bool{
|
|
clientID: false,
|
|
},
|
|
)
|
|
|
|
if assert.NotNil(t, view.ClientOnline) {
|
|
assert.True(t, *view.ClientOnline)
|
|
}
|
|
if assert.NotNil(t, view.AccountSessionOnline) {
|
|
assert.True(t, *view.AccountSessionOnline)
|
|
}
|
|
if assert.NotNil(t, view.TaskConsumerOnline) {
|
|
assert.False(t, *view.TaskConsumerOnline)
|
|
}
|
|
assert.Equal(t, &lastSeen, view.ClientLastSeenAt)
|
|
assert.Equal(t, &deviceName, view.ClientDeviceName)
|
|
}
|
|
|
|
func TestShouldApplyDesktopAccountRuntimeHealth_IgnoresReportOlderThanVerifiedAt(t *testing.T) {
|
|
verifiedAt := time.Date(2026, 4, 30, 9, 30, 0, 0, time.UTC)
|
|
reportCheckedAt := verifiedAt.Add(-time.Minute)
|
|
|
|
shouldApply := shouldApplyDesktopAccountRuntimeHealth(
|
|
DesktopAccountView{
|
|
ID: uuid.NewString(),
|
|
Health: "live",
|
|
VerifiedAt: &verifiedAt,
|
|
},
|
|
bufferedDesktopAccountHealthReport{
|
|
Health: "expired",
|
|
AuthState: "expired",
|
|
CheckedAt: reportCheckedAt,
|
|
},
|
|
)
|
|
|
|
assert.False(t, shouldApply)
|
|
}
|
|
|
|
func TestShouldApplyDesktopAccountRuntimeHealth_AppliesReportAfterVerifiedAt(t *testing.T) {
|
|
verifiedAt := time.Date(2026, 4, 30, 9, 30, 0, 0, time.UTC)
|
|
reportCheckedAt := verifiedAt.Add(time.Minute)
|
|
|
|
shouldApply := shouldApplyDesktopAccountRuntimeHealth(
|
|
DesktopAccountView{
|
|
ID: uuid.NewString(),
|
|
Health: "live",
|
|
VerifiedAt: &verifiedAt,
|
|
},
|
|
bufferedDesktopAccountHealthReport{
|
|
Health: "expired",
|
|
AuthState: "expired",
|
|
CheckedAt: reportCheckedAt,
|
|
},
|
|
)
|
|
|
|
assert.True(t, shouldApply)
|
|
}
|