Files
ttstd-infinite-canvas/backend/internal/app/task_execution_contract_test.go

108 lines
4.0 KiB
Go

package app
import (
"context"
"strings"
"testing"
"yingce/backend/internal/model"
)
func TestAgentMediaAdmissionPersistsOriginAndChargeAuthorization(t *testing.T) {
s, _, args := agentMediaFixture(t)
run, state := agentMediaRun(t, s, args, "auto")
req, _, err := s.prepareCloudAgentMedia(run, &state, agentMediaCall(args))
if err != nil {
t.Fatal(err)
}
req.admission = &taskAdmission{ID: "generation-task", MaxCharge: 1000, AgentRunID: run.ID, GenerationID: "generation", ApprovalID: "approval"}
req.creationPrepare = &creationTaskPreparation{}
task, err := s.CreateTask(run.UserID, req)
if err != nil {
t.Fatal(err)
}
order := req.creationPrepare.Order
if task.AgentRunID != run.ID || task.GenerationID != "generation" || task.ApprovalID != "approval" || order == nil || !order.ChargeLimitSet || task.AuthorizedChargeMicrocredits != order.AmountMicrocredits || order.ChargeLimitMicrocredits != order.AmountMicrocredits {
t.Fatalf("incomplete generation authorization: task=%+v order=%+v", task, order)
}
}
func TestAgentMediaRetryRequiresNewGenerationAuthorization(t *testing.T) {
s, db, _ := agentMediaFixture(t)
for _, task := range []model.Task{
{ID: "agent-run-only", AgentRunID: "run"},
{ID: "generation-only", GenerationID: "generation"},
{ID: "operation-prefix", Operation: "cloud_agent_media"},
{ID: "source", InputJSON: `{"metadata":{"source":"cloud_agent"}}`},
} {
task.UserID, task.Type, task.Status = "user", "canvas_video", model.TaskStatusFailed
if task.Operation == "" {
task.Operation = "image_to_video"
}
if task.InputJSON == "" {
task.InputJSON = `{}`
}
if err := db.Create(&task).Error; err != nil {
t.Fatal(err)
}
if _, err := s.RetryTask(task.UserID, task.ID); err == nil || !strings.Contains(err.Error(), "Agent 重试") {
t.Fatalf("media retry retained old authorization: %v", err)
}
stored, err := s.repo.Task(task.ID)
if err != nil || stored.Status != model.TaskStatusFailed || stored.BillingOrderID != "" {
t.Fatalf("retry changed old execution: %+v %v", stored, err)
}
}
}
func TestOrdinaryFailedAndCancelledTasksKeepRetryIdentity(t *testing.T) {
s, db, _ := agentMediaFixture(t)
for _, status := range []model.TaskStatus{model.TaskStatusFailed, model.TaskStatusCancelled} {
task := model.Task{
ID: "ordinary-" + string(status),
UserID: "user",
Type: "canvas_text",
Operation: "text",
Status: status,
InputJSON: `{}`,
RouteRun: 3,
}
if err := db.Create(&task).Error; err != nil {
t.Fatal(err)
}
retried, err := s.RetryTask(task.UserID, task.ID)
if err != nil {
t.Fatalf("ordinary %s task should remain retryable: %v", status, err)
}
if retried.ID != task.ID || retried.Status != model.TaskStatusQueued || retried.RouteRun != 4 || retried.GenerationID != "" || retried.AgentRunID != "" {
t.Fatalf("retry must reuse task execution identity without inventing an Agent generation: %+v", retried)
}
if _, err = s.RetryTask(task.UserID, task.ID); err == nil {
t.Fatal("queued retry was accepted a second time")
}
}
}
func TestTaskCancellationPersistsFirstSourceAndDiagnostic(t *testing.T) {
s, db, _ := agentMediaFixture(t)
task := model.Task{ID: "cancel-child", UserID: "user", AgentRunID: "parent", Status: model.TaskStatusQueued}
if err := db.Create(&task).Error; err != nil {
t.Fatal(err)
}
if _, err := s.taskLifecycle().cancelTaskWithIntent(context.Background(), "user", task.ID, model.TaskCancellationIntent{Source: model.TaskCancellationParentFailed}); err != nil {
t.Fatal(err)
}
if _, err := s.CancelTask(context.Background(), "user", task.ID); err != nil {
t.Fatal(err)
}
stored, err := s.repo.Task(task.ID)
if err != nil {
t.Fatal(err)
}
diagnostic := taskExecutionDiagnostic(stored)
if stored.CancellationSource != model.TaskCancellationParentFailed || stored.CancellationRequestedAt == nil || diagnostic == nil || diagnostic.Phase != "cancellation" || diagnostic.SubmissionOutcome != "not_submitted" || diagnostic.TaskSubmitted {
t.Fatalf("cancellation lost facts: %+v %+v", stored, diagnostic)
}
}