|
| 1 | +package runtime |
| 2 | + |
| 3 | +//import ( |
| 4 | +// "context" |
| 5 | +// "reflect" |
| 6 | +// "testing" |
| 7 | +// |
| 8 | +// "github.com/cloudimpl/polycode-runtime-go/sdk" |
| 9 | +//) |
| 10 | +// |
| 11 | +//// ---- Mock client that satisfies the full ServiceClient interface ---- |
| 12 | +// |
| 13 | +//type mockServiceClient struct { |
| 14 | +// t *testing.T |
| 15 | +// // Expectations used by ExecService assertions: |
| 16 | +// wantSessionId string |
| 17 | +// wantReq ExecServiceRequest |
| 18 | +// |
| 19 | +// // Return values for ExecService |
| 20 | +// out ExecServiceResponse |
| 21 | +// err error |
| 22 | +// |
| 23 | +// called bool |
| 24 | +//} |
| 25 | +// |
| 26 | +//func (m *mockServiceClient) ExecService(sessionId string, req ExecServiceRequest) (ExecServiceResponse, error) { |
| 27 | +// m.called = true |
| 28 | +// |
| 29 | +// if sessionId != m.wantSessionId { |
| 30 | +// m.t.Fatalf("ExecService: sessionId mismatch: got %q want %q", sessionId, m.wantSessionId) |
| 31 | +// } |
| 32 | +// if req.EnvId != m.wantReq.EnvId { |
| 33 | +// m.t.Fatalf("ExecService: EnvId mismatch: got %q want %q", req.EnvId, m.wantReq.EnvId) |
| 34 | +// } |
| 35 | +// if req.Service != m.wantReq.Service { |
| 36 | +// m.t.Fatalf("ExecService: Service mismatch: got %q want %q", req.Service, m.wantReq.Service) |
| 37 | +// } |
| 38 | +// if req.TenantId != m.wantReq.TenantId { |
| 39 | +// m.t.Fatalf("ExecService: TenantId mismatch: got %q want %q", req.TenantId, m.wantReq.TenantId) |
| 40 | +// } |
| 41 | +// if req.Method != m.wantReq.Method { |
| 42 | +// m.t.Fatalf("ExecService: Method mismatch: got %q want %q", req.Method, m.wantReq.Method) |
| 43 | +// } |
| 44 | +// if req.PartitionKey != m.wantReq.PartitionKey { |
| 45 | +// m.t.Fatalf("ExecService: PartitionKey mismatch: got %q want %q", req.PartitionKey, m.wantReq.PartitionKey) |
| 46 | +// } |
| 47 | +// if got, want := req.Headers[AgentNameHeader], m.wantReq.Headers[AgentNameHeader]; got != want { |
| 48 | +// m.t.Fatalf("ExecService: Headers[%s] mismatch: got %q want %q", AgentNameHeader, got, want) |
| 49 | +// } |
| 50 | +// if !reflect.DeepEqual(req.Options, m.wantReq.Options) { |
| 51 | +// m.t.Fatalf("ExecService: Options mismatch: got %#v want %#v", req.Options, m.wantReq.Options) |
| 52 | +// } |
| 53 | +// if !reflect.DeepEqual(req.Input, m.wantReq.Input) { |
| 54 | +// m.t.Fatalf("ExecService: Input mismatch: got %#v want %#v", req.Input, m.wantReq.Input) |
| 55 | +// } |
| 56 | +// return m.out, m.err |
| 57 | +//} |
| 58 | +// |
| 59 | +//// --- Unused interface methods: return zero values so the type compiles --- |
| 60 | +// |
| 61 | +//func (*mockServiceClient) StartApp(req StartAppRequest) error { return nil } |
| 62 | +//func (*mockServiceClient) ExecApp(string, ExecAppRequest) (ExecAppResponse, error) { |
| 63 | +// return ExecAppResponse{}, nil |
| 64 | +//} |
| 65 | +//func (*mockServiceClient) ExecApi(string, ExecApiRequest) (ExecApiResponse, error) { |
| 66 | +// return ExecApiResponse{}, nil |
| 67 | +//} |
| 68 | +//func (*mockServiceClient) ExecFunc(string, ExecFuncRequest) (ExecFuncResponse, error) { |
| 69 | +// return ExecFuncResponse{}, nil |
| 70 | +//} |
| 71 | +//func (*mockServiceClient) ExecFuncResult(string, ExecFuncResult) error { return nil } |
| 72 | +//func (*mockServiceClient) GetItem(string, QueryRequest) (map[string]interface{}, error) { |
| 73 | +// return nil, nil |
| 74 | +//} |
| 75 | +//func (*mockServiceClient) UnsafeGetItem(string, UnsafeQueryRequest) (map[string]interface{}, error) { |
| 76 | +// return nil, nil |
| 77 | +//} |
| 78 | +//func (*mockServiceClient) QueryItems(string, QueryRequest) ([]map[string]interface{}, error) { |
| 79 | +// return nil, nil |
| 80 | +//} |
| 81 | +//func (*mockServiceClient) UnsafeQueryItems(string, UnsafeQueryRequest) ([]map[string]interface{}, error) { |
| 82 | +// return nil, nil |
| 83 | +//} |
| 84 | +//func (*mockServiceClient) PutItem(string, PutRequest) error { return nil } |
| 85 | +//func (*mockServiceClient) UnsafePutItem(string, UnsafePutRequest) error { return nil } |
| 86 | +//func (*mockServiceClient) GetFile(string, GetFileRequest) (GetFileResponse, error) { |
| 87 | +// return GetFileResponse{}, nil |
| 88 | +//} |
| 89 | +//func (*mockServiceClient) GetFileDownloadLink(string, GetFileRequest) (GetLinkResponse, error) { |
| 90 | +// return GetLinkResponse{}, nil |
| 91 | +//} |
| 92 | +//func (*mockServiceClient) PutFile(string, PutFileRequest) error { return nil } |
| 93 | +//func (*mockServiceClient) GetFileUploadLink(string, GetUploadLinkRequest) (GetLinkResponse, error) { |
| 94 | +// return GetLinkResponse{}, nil |
| 95 | +//} |
| 96 | +//func (*mockServiceClient) DeleteFile(string, DeleteFileRequest) error { return nil } |
| 97 | +//func (*mockServiceClient) RenameFile(string, RenameFileRequest) error { return nil } |
| 98 | +//func (*mockServiceClient) ListFile(string, ListFilePageRequest) (ListFilePageResponse, error) { |
| 99 | +// return ListFilePageResponse{}, nil |
| 100 | +//} |
| 101 | +//func (*mockServiceClient) CreateFolder(string, CreateFolderRequest) error { return nil } |
| 102 | +//func (*mockServiceClient) EmitSignal(string, SignalEmitRequest) error { return nil } |
| 103 | +//func (*mockServiceClient) WaitForSignal(string, SignalWaitRequest) (SignalWaitResponse, error) { |
| 104 | +// return SignalWaitResponse{}, nil |
| 105 | +//} |
| 106 | +//func (*mockServiceClient) EmitRealtimeEvent(string, RealtimeEventEmitRequest) error { return nil } |
| 107 | +//func (*mockServiceClient) AcquireLock(string, AcquireLockRequest) error { return nil } |
| 108 | +//func (*mockServiceClient) ReleaseLock(string, ReleaseLockRequest) error { return nil } |
| 109 | +//func (*mockServiceClient) IncrementCounter(string, IncrementCounterRequest) (IncrementCounterResponse, error) { |
| 110 | +// return IncrementCounterResponse{}, nil |
| 111 | +//} |
| 112 | +//func (*mockServiceClient) GetMeta(string, GetMetaDataRequest) (map[string]interface{}, error) { |
| 113 | +// return nil, nil |
| 114 | +//} |
| 115 | +//func (*mockServiceClient) Acknowledge(string) error { return nil } |
| 116 | +// |
| 117 | +//// ---- Tests ---- |
| 118 | +// |
| 119 | +//func TestAgentBuilder_WithTenantIdAndGet(t *testing.T) { |
| 120 | +// ctx := context.Background() |
| 121 | +// mock := &mockServiceClient{t: t} |
| 122 | +// |
| 123 | +// b := AgentBuilder{ |
| 124 | +// ctx: ctx, |
| 125 | +// sessionId: "sess-123", |
| 126 | +// envId: "env-1", |
| 127 | +// agent: "echo", |
| 128 | +// serviceClient: mock, |
| 129 | +// } |
| 130 | +// |
| 131 | +// aIface := b.WithTenantId("tenant-xyz").Get() |
| 132 | +// a, ok := aIface.(Agent) |
| 133 | +// if !ok { |
| 134 | +// t.Fatalf("Get() did not return concrete Agent type") |
| 135 | +// } |
| 136 | +// |
| 137 | +// if a.tenantId != "tenant-xyz" || a.envId != "env-1" || a.agent != "echo" || a.sessionId != "sess-123" || a.ctx != ctx { |
| 138 | +// t.Fatalf("Agent fields not propagated correctly: %+v", a) |
| 139 | +// } |
| 140 | +//} |
| 141 | +// |
| 142 | +//func TestAgentCall_Success(t *testing.T) { |
| 143 | +// ctx := context.Background() |
| 144 | +// agentName := "echo" |
| 145 | +// input := sdk.AgentInput{SessionKey: "user-session-42"} |
| 146 | +// var opts sdk.TaskOptions |
| 147 | +// |
| 148 | +// wantReq := ExecServiceRequest{ |
| 149 | +// EnvId: "env-1", |
| 150 | +// Service: "agent-service", |
| 151 | +// TenantId: "tenant-xyz", |
| 152 | +// PartitionKey: agentName + ":" + input.SessionKey, |
| 153 | +// Method: "CallAgent", |
| 154 | +// Options: opts, |
| 155 | +// Headers: map[string]string{AgentNameHeader: agentName}, |
| 156 | +// Input: input, |
| 157 | +// } |
| 158 | +// |
| 159 | +// mock := &mockServiceClient{ |
| 160 | +// t: t, |
| 161 | +// wantSessionId: "sess-123", |
| 162 | +// wantReq: wantReq, |
| 163 | +// out: ExecServiceResponse{ |
| 164 | +// IsError: false, |
| 165 | +// Output: map[string]any{"ok": true, "msg": "pong"}, |
| 166 | +// // Error zero-value |
| 167 | +// }, |
| 168 | +// err: nil, |
| 169 | +// } |
| 170 | +// |
| 171 | +// a := Agent{ |
| 172 | +// ctx: ctx, |
| 173 | +// sessionId: "sess-123", |
| 174 | +// envId: "env-1", |
| 175 | +// agent: agentName, |
| 176 | +// serviceClient: mock, |
| 177 | +// tenantId: "tenant-xyz", |
| 178 | +// } |
| 179 | +// |
| 180 | +// respIface := a.Call(opts, input) |
| 181 | +// resp, ok := respIface.(Response) |
| 182 | +// if !ok { |
| 183 | +// t.Fatalf("Call() did not return concrete Response type") |
| 184 | +// } |
| 185 | +// |
| 186 | +// if !mock.called { |
| 187 | +// t.Fatalf("ExecService was not called") |
| 188 | +// } |
| 189 | +// if resp.isError { |
| 190 | +// t.Fatalf("expected isError=false, got true (err=%+v)", resp.error) |
| 191 | +// } |
| 192 | +// if !reflect.DeepEqual(resp.output, mock.out.Output) { |
| 193 | +// t.Fatalf("output mismatch: got %#v want %#v", resp.output, mock.out.Output) |
| 194 | +// } |
| 195 | +//} |
| 196 | +// |
| 197 | +//func TestAgentCall_ExecError(t *testing.T) { |
| 198 | +// ctx := context.Background() |
| 199 | +// agentName := "alpha" |
| 200 | +// input := sdk.AgentInput{SessionKey: "s-1"} |
| 201 | +// var opts sdk.TaskOptions |
| 202 | +// |
| 203 | +// wantReq := ExecServiceRequest{ |
| 204 | +// EnvId: "env-A", |
| 205 | +// Service: "agent-service", |
| 206 | +// TenantId: "tenant-A", |
| 207 | +// PartitionKey: agentName + ":" + input.SessionKey, |
| 208 | +// Method: "CallAgent", |
| 209 | +// Options: opts, |
| 210 | +// Headers: map[string]string{AgentNameHeader: agentName}, |
| 211 | +// Input: input, |
| 212 | +// } |
| 213 | +// |
| 214 | +// mock := &mockServiceClient{ |
| 215 | +// t: t, |
| 216 | +// wantSessionId: "sess-A", |
| 217 | +// wantReq: wantReq, |
| 218 | +// out: ExecServiceResponse{}, // ignored on error |
| 219 | +// err: assertableError{"boom-123"}, // triggers error path |
| 220 | +// } |
| 221 | +// |
| 222 | +// a := Agent{ |
| 223 | +// ctx: ctx, |
| 224 | +// sessionId: "sess-A", |
| 225 | +// envId: "env-A", |
| 226 | +// agent: agentName, |
| 227 | +// serviceClient: mock, |
| 228 | +// tenantId: "tenant-A", |
| 229 | +// } |
| 230 | +// |
| 231 | +// respIface := a.Call(opts, input) |
| 232 | +// resp, ok := respIface.(Response) |
| 233 | +// if !ok { |
| 234 | +// t.Fatalf("Call() did not return concrete Response type") |
| 235 | +// } |
| 236 | +// |
| 237 | +// if !mock.called { |
| 238 | +// t.Fatalf("ExecService was not called") |
| 239 | +// } |
| 240 | +// if !resp.isError { |
| 241 | +// t.Fatalf("expected isError=true, got false") |
| 242 | +// } |
| 243 | +//} |
| 244 | +// |
| 245 | +//// Tiny error type for the error-path test |
| 246 | +//type assertableError struct{ msg string } |
| 247 | +// |
| 248 | +//func (e assertableError) Error() string { return e.msg } |
0 commit comments