|
27 | 27 | import com.tencent.trpc.core.exception.TRpcException; |
28 | 28 | import com.tencent.trpc.core.rpc.ProviderInvoker; |
29 | 29 | import com.tencent.trpc.core.rpc.RpcInvocation; |
| 30 | +import com.tencent.trpc.core.rpc.Response; |
30 | 31 | import com.tencent.trpc.core.rpc.common.RpcMethodInfo; |
31 | 32 | import com.tencent.trpc.core.rpc.common.RpcMethodInfoAndInvoker; |
32 | 33 | import com.tencent.trpc.core.rpc.def.DefRequest; |
@@ -140,4 +141,101 @@ public void handleError_shouldHandleErrorCorrectly() throws Exception { |
140 | 141 | verify(response).setStatus(HttpStatus.SC_SERVICE_UNAVAILABLE); |
141 | 142 | verify(httpCodec).writeHttpResponse(any(HttpServletResponse.class), any()); |
142 | 143 | } |
| 144 | + |
| 145 | + @Test |
| 146 | + public void invokeRpcRequest_shouldHandleThrowable() throws Exception { |
| 147 | + AbstractHttpExecutor abstractHttpExecutor = mock(AbstractHttpExecutor.class); |
| 148 | + ProviderInvoker<?> invoker = mock(ProviderInvoker.class); |
| 149 | + ProviderConfig providerConfig = mock(ProviderConfig.class); |
| 150 | + WorkerPool workerPool = mock(WorkerPool.class); |
| 151 | + HttpServletResponse response = mock(HttpServletResponse.class); |
| 152 | + HttpServletRequest request = mock(HttpServletRequest.class); |
| 153 | + DefRequest defRequest = new DefRequest(); |
| 154 | + AtomicBoolean responded = new AtomicBoolean(false); |
| 155 | + CompletableFuture<Void> completionFuture = new CompletableFuture<>(); |
| 156 | + HttpCodec httpCodec = mock(HttpCodec.class); |
| 157 | + Whitebox.setInternalState(abstractHttpExecutor, "httpCodec", httpCodec); |
| 158 | + |
| 159 | + defRequest.getAttachments().put(HttpConstants.TRPC_ATTACH_SERVLET_RESPONSE, response); |
| 160 | + defRequest.getAttachments().put(HttpConstants.TRPC_ATTACH_SERVLET_REQUEST, request); |
| 161 | + |
| 162 | + when(invoker.getConfig()).thenReturn(providerConfig); |
| 163 | + when(providerConfig.getWorkerPoolObj()).thenReturn(workerPool); |
| 164 | + |
| 165 | + doAnswer(invocation -> { |
| 166 | + Object arg = invocation.getArguments()[0]; |
| 167 | + if (arg instanceof Runnable) { |
| 168 | + ((Runnable) arg).run(); |
| 169 | + } else if (arg instanceof Task) { |
| 170 | + ((Task) arg).run(); |
| 171 | + } |
| 172 | + return null; |
| 173 | + }).when(workerPool).execute(any()); |
| 174 | + |
| 175 | + CompletableFuture<Response> failedFuture = new CompletableFuture<>(); |
| 176 | + failedFuture.completeExceptionally(new RuntimeException("boom")); |
| 177 | + when(invoker.invoke(any())).thenReturn(failedFuture); |
| 178 | + doReturn(response).when(abstractHttpExecutor, "getOriginalResponse", any()); |
| 179 | + doReturn(request).when(abstractHttpExecutor, "getOriginalRequest", any()); |
| 180 | + doCallRealMethod().when(abstractHttpExecutor, "invokeRpcRequest", any(), any(), any(), any()); |
| 181 | + doCallRealMethod().when(abstractHttpExecutor, "httpErrorReply", any(), any(), any()); |
| 182 | + doCallRealMethod().when(abstractHttpExecutor, "handleError", any(Throwable.class), any(DefRequest.class), |
| 183 | + any(HttpServletResponse.class), any(AtomicBoolean.class), any(CompletableFuture.class)); |
| 184 | + |
| 185 | + Whitebox.invokeMethod(abstractHttpExecutor, "invokeRpcRequest", invoker, defRequest, completionFuture, |
| 186 | + responded); |
| 187 | + |
| 188 | + assertEquals(true, responded.get()); |
| 189 | + assertEquals(true, completionFuture.isCompletedExceptionally()); |
| 190 | + verify(response).setStatus(org.apache.http.HttpStatus.SC_SERVICE_UNAVAILABLE); |
| 191 | + verify(httpCodec).writeHttpResponse(any(HttpServletResponse.class), any()); |
| 192 | + } |
| 193 | + |
| 194 | + @Test |
| 195 | + public void invokeRpcRequest_shouldHandleInvokeThrowsExceptionDirectly() throws Exception { |
| 196 | + AbstractHttpExecutor abstractHttpExecutor = mock(AbstractHttpExecutor.class); |
| 197 | + ProviderInvoker<?> invoker = mock(ProviderInvoker.class); |
| 198 | + ProviderConfig providerConfig = mock(ProviderConfig.class); |
| 199 | + WorkerPool workerPool = mock(WorkerPool.class); |
| 200 | + HttpServletResponse response = mock(HttpServletResponse.class); |
| 201 | + HttpServletRequest request = mock(HttpServletRequest.class); |
| 202 | + DefRequest defRequest = new DefRequest(); |
| 203 | + AtomicBoolean responded = new AtomicBoolean(false); |
| 204 | + CompletableFuture<Void> completionFuture = new CompletableFuture<>(); |
| 205 | + HttpCodec httpCodec = mock(HttpCodec.class); |
| 206 | + Whitebox.setInternalState(abstractHttpExecutor, "httpCodec", httpCodec); |
| 207 | + |
| 208 | + defRequest.getAttachments().put(HttpConstants.TRPC_ATTACH_SERVLET_RESPONSE, response); |
| 209 | + defRequest.getAttachments().put(HttpConstants.TRPC_ATTACH_SERVLET_REQUEST, request); |
| 210 | + |
| 211 | + when(invoker.getConfig()).thenReturn(providerConfig); |
| 212 | + when(providerConfig.getWorkerPoolObj()).thenReturn(workerPool); |
| 213 | + |
| 214 | + doAnswer(invocation -> { |
| 215 | + Object arg = invocation.getArguments()[0]; |
| 216 | + if (arg instanceof Runnable) { |
| 217 | + ((Runnable) arg).run(); |
| 218 | + } else if (arg instanceof Task) { |
| 219 | + ((Task) arg).run(); |
| 220 | + } |
| 221 | + return null; |
| 222 | + }).when(workerPool).execute(any()); |
| 223 | + |
| 224 | + when(invoker.invoke(any())).thenThrow(new RuntimeException("boom-direct")); |
| 225 | + |
| 226 | + doReturn(response).when(abstractHttpExecutor, "getOriginalResponse", any()); |
| 227 | + doReturn(request).when(abstractHttpExecutor, "getOriginalRequest", any()); |
| 228 | + doCallRealMethod().when(abstractHttpExecutor, "invokeRpcRequest", any(), any(), any(), any()); |
| 229 | + doCallRealMethod().when(abstractHttpExecutor, "httpErrorReply", any(), any(), any()); |
| 230 | + doCallRealMethod().when(abstractHttpExecutor, "handleError", any(Throwable.class), any(DefRequest.class), |
| 231 | + any(HttpServletResponse.class), any(AtomicBoolean.class), any(CompletableFuture.class)); |
| 232 | + |
| 233 | + Whitebox.invokeMethod(abstractHttpExecutor, "invokeRpcRequest", invoker, defRequest, completionFuture, |
| 234 | + responded); |
| 235 | + |
| 236 | + assertEquals(true, responded.get()); |
| 237 | + assertEquals(true, completionFuture.isCompletedExceptionally()); |
| 238 | + verify(response).setStatus(HttpStatus.SC_SERVICE_UNAVAILABLE); |
| 239 | + verify(httpCodec).writeHttpResponse(any(HttpServletResponse.class), any()); |
| 240 | + } |
143 | 241 | } |
0 commit comments