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
81 lines
2.8 KiB
Go
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)
|
|
}
|
|
})
|
|
}
|
|
}
|