package rpc import ( "context" "strings" "testing" "time" agentpb "git.ipao.vip/rogee/go-sip/gen/agent" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" ) func TestUploadBindingAndExpiryGuards(t *testing.T) { now := time.Unix(100, 0) server := NewServer(ServerOptions{ Now: func() time.Time { return now }, UploadPolicy: &agentpb.UploadPolicy{Enabled: true, MaxAssetBytes: 1024}, }) _, err := server.ActivateAgent(context.Background(), &agentpb.ActivateAgentRequest{ Meta: testMeta("activate-upload", "", 0), Binding: &agentpb.AgentBinding{AgentId: "agent-1", CellId: "cell-1", ExpectedBootId: "boot-1", DispatcherEpoch: "epoch-1", SessionGeneration: 1}, ActivationOperationId: "activate-upload", SessionExpiresAtUnixMs: now.Add(time.Hour).UnixMilli(), }) if err != nil { t.Fatal(err) } binding := &agentpb.ExecutionBinding{TenantId: "tenant-1", TenantKey: "tenant-demo-key", ExecutionId: "execution-upload", TaskId: "task-upload", TaskItemId: "item-upload", TaskRevision: 1} asset := &agentpb.AssetDescriptor{Kind: agentpb.AssetKind_ASSET_KIND_RECORDING, AssetId: "recording-upload", ExecutionId: binding.ExecutionId, Format: "wav", SizeBytes: 4, ChecksumSha256: strings.Repeat("a", 64), Channels: 1, SampleRateHz: 16000, DurationMs: 1} request := &agentpb.RequestUploadRequest{Meta: testMeta("upload-request", "upload-request-key", 1), Binding: binding, Asset: asset, UploadId: "upload-binding"} created, err := server.RequestUpload(context.Background(), request) if err != nil { t.Fatal(err) } if created.Grant == nil || created.Grant.ExpiresAtUnixMs <= now.UnixMilli() { t.Fatalf("invalid grant: %+v", created.Grant) } mismatched := proto.Clone(request).(*agentpb.RequestUploadRequest) mismatched.Meta = testMeta("upload-conflict", "upload-conflict-key", 1) mismatched.Binding = proto.Clone(binding).(*agentpb.ExecutionBinding) mismatched.Binding.ExecutionId = "other-execution" conflict, err := server.RequestUpload(context.Background(), mismatched) if err != nil { t.Fatal(err) } if conflict.Receipt == nil || conflict.Receipt.Result != agentpb.ResultCode_RESULT_CODE_CONFLICT { t.Fatalf("unexpected upload conflict: %+v", conflict) } now = now.Add(6 * time.Minute) completed, err := server.CompleteUpload(context.Background(), &agentpb.CompleteUploadRequest{ Meta: testMeta("upload-complete-expired", "upload-complete-expired-key", 1), Binding: binding, Asset: asset, UploadId: request.UploadId, UploadedSizeBytes: asset.SizeBytes, UploadedChecksumSha256: asset.ChecksumSha256, }) if err != nil { t.Fatal(err) } if completed.Receipt == nil || completed.Receipt.Result != agentpb.ResultCode_RESULT_CODE_REJECTED || completed.Receipt.Failure == nil || completed.Receipt.Failure.Code != agentpb.FailureCode_FAILURE_CODE_FAILED_PRECONDITION { t.Fatalf("unexpected expired completion: %+v", completed) } if status.Code(err) != codes.OK { t.Fatalf("unexpected status code: %s", status.Code(err)) } }