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

81 lines
2.8 KiB
Go

package activityreplication_test
import (
"encoding/json"
"errors"
"testing"
activityreplication "github.com/tutti-os/tutti/packages/agent/activity-replication"
)
func TestLegacyCommandStateOnlyDecodesAsDeleteTombstone(t *testing.T) {
t.Parallel()
var mutation activityreplication.Mutation
if err := json.Unmarshal([]byte(`{
"schemaVersion": 1,
"mutationId": "delete-operation",
"transactionId": "transaction-1",
"sourceDeviceId": "device-1",
"workspaceId": "workspace-1",
"entityType": "runtimeOperation",
"operation": "delete",
"key": {"agentSessionId": "session-1", "operationId": "operation-1"}
}`), &mutation); err != nil {
t.Fatalf("Unmarshal() error = %v", err)
}
if err := activityreplication.ValidateMutation(mutation); err != nil {
t.Fatalf("ValidateMutation(delete) error = %v", err)
}
mutation.Operation = activityreplication.OperationUpsert
if err := activityreplication.ValidateMutation(mutation); err == nil {
t.Fatal("ValidateMutation(upsert) error = nil, want permanent schema rejection")
} else {
var rejection *activityreplication.PermanentRejection
if !errors.As(err, &rejection) || rejection.Kind != activityreplication.RejectionSchema ||
rejection.MutationID != mutation.MutationID || rejection.TransactionID != mutation.TransactionID {
t.Fatalf("ValidateMutation(upsert) error = %#v", err)
}
}
}
func TestAcknowledgementSemantics(t *testing.T) {
t.Parallel()
mutation := activityreplication.Mutation{MutationID: "mutation-1", TransactionID: "transaction-retry"}
result, err := activityreplication.SummarizeAcknowledgements([]activityreplication.MutationAcknowledgement{
activityreplication.AcknowledgeDuplicate(mutation, 7),
activityreplication.AcknowledgeStale(mutation),
activityreplication.AcknowledgeApplied(mutation, 9),
})
if err != nil {
t.Fatalf("SummarizeAcknowledgements() error = %v", err)
}
if result.AcceptedCount != 3 || result.Cursor != 9 {
t.Fatalf("SummarizeAcknowledgements() = %#v", result)
}
}
func TestPermanentRejectionsPreserveMutationAndTransactionIdentity(t *testing.T) {
t.Parallel()
mutation := activityreplication.Mutation{MutationID: "mutation-1", TransactionID: "transaction-1"}
for _, kind := range []activityreplication.RejectionKind{
activityreplication.RejectionSchema,
activityreplication.RejectionIdentity,
activityreplication.RejectionPermission,
} {
kind := kind
t.Run(string(kind), func(t *testing.T) {
t.Parallel()
err := activityreplication.NewPermanentRejection(kind, mutation, errors.New("rejected"))
var rejection *activityreplication.PermanentRejection
if !errors.As(err, &rejection) || rejection.Kind != kind || rejection.MutationID != mutation.MutationID ||
rejection.TransactionID != mutation.TransactionID {
t.Fatalf("NewPermanentRejection() = %#v", err)
}
})
}
}