Files
go-sip/cmd/sip-go-agent/upload_attempt_test.go
T

85 lines
3.2 KiB
Go

package main
import (
"context"
"crypto/sha256"
"encoding/hex"
"errors"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"testing"
"time"
agentpb "git.ipao.vip/rogee/go-sip/gen/agent"
"git.ipao.vip/rogee/go-sip/internal/agent"
"git.ipao.vip/rogee/go-sip/internal/config"
)
type uploadRPCStub struct {
grant *agentpb.UploadGrant
requests, notifications int
pending bool
}
func (s *uploadRPCStub) RequestUpload(_ context.Context, r *agentpb.RequestUploadRequest) (*agentpb.RequestUploadResponse, error) {
s.requests++
s.grant.UploadId = r.UploadId
return &agentpb.RequestUploadResponse{Grant: s.grant, Receipt: &agentpb.OperationReceipt{Result: agentpb.ResultCode_RESULT_CODE_ACCEPTED}}, nil
}
func (s *uploadRPCStub) CompleteUpload(_ context.Context, _ *agentpb.CompleteUploadRequest) (*agentpb.CompleteUploadResponse, error) {
s.notifications++
if s.pending {
return nil, errors.New("notification pending")
}
return &agentpb.CompleteUploadResponse{State: agentpb.UploadState_UPLOAD_STATE_COMPLETED, Receipt: &agentpb.OperationReceipt{Result: agentpb.ResultCode_RESULT_CODE_ACCEPTED}}, nil
}
func TestRecordingNotificationRecoveryDoesNotPUTAgain(t *testing.T) {
puts := 0
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { puts++; w.WriteHeader(http.StatusOK) }))
defer server.Close()
root := t.TempDir()
path := filepath.Join(root, "audio.wav")
if err := os.WriteFile(path, []byte("audio"), 0600); err != nil {
t.Fatal(err)
}
sum := sha256.Sum256([]byte("audio"))
binding := &agentpb.ExecutionBinding{TenantId: "tenant-a", TenantKey: "tenant-a", ExecutionId: "execution-a", CallId: "call-a"}
asset := &agentpb.AssetDescriptor{AssetId: "recording-a", SizeBytes: 5, ChecksumSha256: hex.EncodeToString(sum[:])}
remote := &uploadRPCStub{pending: true, grant: &agentpb.UploadGrant{ObjectKey: "recording-a", Bucket: "mock-bucket", TargetUrl: server.URL, MaxBytes: 5, RequiredChecksumSha256: asset.ChecksumSha256, ExpiresAtUnixMs: time.Now().Add(time.Minute).UnixMilli()}}
spool, err := agent.NewSpool(root, nil)
if err != nil {
t.Fatal(err)
}
uploader := agent.UploadClient{HTTPClient: server.Client()}
if _, err := uploadRecording(context.Background(), config.Config{}, remote, uploader, spool, binding, asset, path); err == nil {
t.Fatal("pending MQ notification reported complete")
}
remote.pending = false
restarted, err := agent.NewSpool(root, nil)
if err != nil {
t.Fatal(err)
}
if err := recoverUploadNotifications(context.Background(), config.Config{}, remote, restarted); err != nil {
t.Fatal(err)
}
record, err := restarted.LoadUploadAttempt(stableUploadID(binding, asset))
if err != nil {
t.Fatal(err)
}
if record.State != "completed" || puts != 1 || remote.requests != 1 || remote.notifications != 2 {
t.Fatalf("state=%s PUT=%d grant=%d notification=%d", record.State, puts, remote.requests, remote.notifications)
}
if _, err := uploadRecording(context.Background(), config.Config{}, remote, uploader, restarted, binding, asset, path); err != nil {
t.Fatal(err)
}
if puts != 1 || remote.notifications != 2 {
t.Fatal("completed upload repeated side effects")
}
if _, err := os.Stat(path); err != nil {
t.Fatal("source recording removed")
}
}