Files
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

107 lines
4.0 KiB
Go

package daemon
import (
"context"
"path/filepath"
"testing"
"time"
marketdata "github.com/tutti-os/tutti/packages/connector/daemon/adapters/sqlite"
market "github.com/tutti-os/tutti/packages/connector/daemon/core"
)
func TestRuntimeConvergenceWorkerAppliesDurableDesiredState(t *testing.T) {
ctx := context.Background()
store, err := marketdata.Open(ctx, filepath.Join(t.TempDir(), "tuttid.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = store.Close() })
release := hostTestRelease()
connector := market.Connector{
Key: release.ConnectorKey, Release: release,
Installation: market.Installation{
State: market.InstallationStateInstalled, InstalledVersion: release.Version,
InstalledReleaseID: release.ReleaseID, InstalledReleaseDigest: release.ReleaseDigest,
},
Authorization: market.Authorization{State: market.AuthorizationStateNotRequired},
Compatibility: market.Compatibility{State: market.CompatibilityStateSupported},
}
now := time.Date(2026, 8, 15, 4, 0, 0, 0, time.UTC)
install := market.Operation{
OperationID: "install-1", ClientRequestID: "install-request-1", ConnectorKey: connector.Key,
Kind: market.OperationKindInstall, State: market.OperationStateCompleted, Stage: market.OperationStageCompleted,
Target: &market.OperationTarget{
ConnectorKey: connector.Key, Version: release.Version, ReleaseID: release.ReleaseID,
ReleaseDigest: release.ReleaseDigest, Release: &release,
},
CreatedAt: now, UpdatedAt: now,
}
desired := market.RuntimeConvergence{
Desired: market.RuntimeDesired{
ConnectorKey: connector.Key, Generation: 1, Enabled: true,
ConnectionID: "device-github", ReleaseDigest: release.ReleaseDigest,
AuthorizationState: market.AuthorizationStateNotRequired, UpdatedAt: now,
},
NextAttemptAt: now,
UpdatedAt: now,
}
if err := store.Transaction(ctx, func(tx market.Transaction) error {
connector.Revision = tx.AdvanceRevision()
if err := tx.SaveConnector(connector); err != nil {
return err
}
if err := tx.SaveOperation(install); err != nil {
return err
}
return tx.SaveRuntimeConvergence(desired)
}); err != nil {
t.Fatal(err)
}
runtime := &activationGateDelegate{}
gate := newActivationGateHost(runtime)
gate.setOpen(market.OperationScope{}, true)
scheduler := NewOperationScheduler(ctx)
application, err := market.NewApplication(market.ApplicationConfig{
Repository: store, CatalogSource: &countingCatalogSource{release: release},
ReleaseInstallations: runtime, Host: gate, Authorization: unavailableAuthorization{},
RuntimeBindings: runtimeBindingResolverFunc(func(context.Context, market.RuntimeBindingRequest) (market.RuntimeBinding, error) {
return market.RuntimeBinding{
ConnectionID: "device-github", Enabled: true, AuthorizationState: market.AuthorizationStateNotRequired,
}, nil
}),
Compatibility: rejectingCompatibility{}, Scheduler: scheduler,
ImplementationRegistry: market.NewImplementationRegistry(nil),
Now: func() time.Time { return now },
BootEpoch: "boot-1",
WorkerID: "worker-1",
})
if err != nil {
t.Fatal(err)
}
if err := scheduler.Bind(application); err != nil {
t.Fatal(err)
}
host := &Host{Application: application, bootstrapped: true,
runtimeRecoveryPending: map[string]struct{}{connector.Key: {}}}
if err := host.convergeDueRuntimes(ctx); err != nil {
t.Fatal(err)
}
if runtime.reconciles != 0 {
t.Fatalf("runtime converged before post-fence planning completed: %d", runtime.reconciles)
}
delete(host.runtimeRecoveryPending, connector.Key)
if err := host.convergeDueRuntimes(ctx); err != nil {
t.Fatal(err)
}
stored, err := store.RuntimeConvergence(ctx, market.OperationScope{}, connector.Key)
if err != nil {
t.Fatal(err)
}
if runtime.reconciles != 1 || stored.Observed.DesiredGeneration != 1 ||
stored.Observed.BootEpoch != "boot-1" || stored.Observed.Readiness.State != market.RuntimeReadinessReady {
t.Fatalf("runtime reconciles = %d, convergence = %#v", runtime.reconciles, stored)
}
}