package rpc import ( "context" "encoding/json" "net" "os" "path/filepath" "testing" "time" agentpb "git.ipao.vip/rogee/go-sip/gen/agent" "git.ipao.vip/rogee/go-sip/internal/configread" "git.ipao.vip/rogee/go-sip/internal/dispatcher" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/test/bufconn" ) func mockApprovedGRPC(t *testing.T, server *Server) agentpb.AgentControlServiceClient { t.Helper() listener := bufconn.Listen(1 << 20) grpcServer := grpc.NewServer() agentpb.RegisterAgentControlServiceServer(grpcServer, server) go func() { _ = grpcServer.Serve(listener) }() t.Cleanup(grpcServer.Stop) t.Cleanup(func() { _ = listener.Close() }) conn, err := grpc.NewClient("bufnet", grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) { return listener.Dial() }), grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = conn.Close() }) return agentpb.NewAgentControlServiceClient(conn) } func TestApprovedDispatcherToAgentUnaryMockRetainsSnapshotAndOneShotCall(t *testing.T) { now := time.Date(2026, 9, 20, 10, 0, 0, 0, time.UTC) req := approvedTestRequest(t, now) calls := 0 agent := activatedApprovedServer(t, now, filepath.Join(t.TempDir(), "agent-session.json"), req.DispatcherId, 1, func(_ context.Context, call ApprovedExecution) error { calls++ if call.SIPRevision != 8 || call.AI.Mode != "asr_only" || call.AI.ASR.Provider.Credential != "sk-******" || call.MaxCallDuration != 20*time.Second { t.Fatal("Agent received the wrong frozen execution configuration") } return nil }) client := mockApprovedGRPC(t, agent) orig := &dispatcher.ApprovedOriginator{DispatcherID: req.DispatcherId, Client: client, Meta: func(context.Context) (*agentpb.RequestMeta, error) { return testMeta("inspect-loaded", "", 1), nil }, } sipJSON, err := os.ReadFile("../../contracts/schema/examples/config-read-sip.json") if err != nil { t.Fatal(err) } var sip configread.SIP if err := json.Unmarshal(sipJSON, &sip); err != nil { t.Fatal(err) } var task configread.Task if err := json.Unmarshal(req.TaskConfigJson, &task); err != nil { t.Fatal(err) } var providers map[string]configread.Provider if err := json.Unmarshal(req.ProvidersJson, &providers); err != nil { t.Fatal(err) } snapshot := configread.Snapshot{SIP: sip, Task: task, Providers: providers} if err := orig.VerifySIP(context.Background(), sip); err != nil { t.Fatal(err) } spec := dispatcher.CallSpec{ EventID: req.SourceEventId, TaskID: task.TaskID, TenantID: task.TenantID, TrunkID: req.SelectedTrunkId, Callee: req.Callee, DialedCallee: req.DialedCallee, CallerID: req.CallerId, RingTimeoutMS: req.RingTimeoutMs, MaxCallDurationMS: req.MaxCallDurationMs, Deadline: time.UnixMilli(req.DialBeforeUnixMs), Snapshot: snapshot, } if err := orig.Originate(context.Background(), spec); err != nil || calls != 1 { t.Fatalf("approved mock call was not accepted once: calls=%d err=%v", calls, err) } if err := orig.Originate(context.Background(), spec); err == nil || calls != 1 { t.Fatalf("duplicate unary call must not redial: calls=%d err=%v", calls, err) } }