This is an automated email from the ASF dual-hosted git repository. liubao pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
commit 15b85a5d0b0ae0457be40b5f93bc894b4d440bd5 Author: wujimin <[email protected]> AuthorDate: Sat Apr 21 21:17:29 2018 +0800 [SCB-486] refactoring VertxHttpMethod to RestClientInvocation: move method parameters to be fields, not change any logic --- .../test/scaffolding/log/LogCollector.java | 6 + .../transport-rest/transport-rest-client/pom.xml | 66 ++--- .../transport/rest/client/RestTransportClient.java | 16 +- ...txHttpMethod.java => RestClientInvocation.java} | 97 ++++--- .../rest/client/http/TestRestClientInvocation.java | 302 +++++++++++++++++++++ .../rest/client/http/TestVertxHttpMethod.java | 302 --------------------- 6 files changed, 407 insertions(+), 382 deletions(-) diff --git a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java index 33e5808..53359e3 100644 --- a/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java +++ b/foundations/foundation-test-scaffolding/src/main/java/org/apache/servicecomb/foundation/test/scaffolding/log/LogCollector.java @@ -21,6 +21,7 @@ import java.util.List; import org.apache.log4j.Appender; import org.apache.log4j.AppenderSkeleton; +import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.spi.LoggingEvent; @@ -48,6 +49,11 @@ public class LogCollector { Logger.getRootLogger().addAppender(appender); } + public LogCollector setLogLevel(String logName, Level level) { + Logger.getLogger(logName).setLevel(level); + return this; + } + public List<LoggingEvent> getEvents() { return events; } diff --git a/transports/transport-rest/transport-rest-client/pom.xml b/transports/transport-rest/transport-rest-client/pom.xml index d7e2996..d7f0363 100644 --- a/transports/transport-rest/transport-rest-client/pom.xml +++ b/transports/transport-rest/transport-rest-client/pom.xml @@ -16,36 +16,40 @@ ~ limitations under the License. --> -<project - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" - xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <modelVersion>4.0.0</modelVersion> - <parent> - <groupId>org.apache.servicecomb</groupId> - <artifactId>transport-rest</artifactId> - <version>1.0.0-m2-SNAPSHOT</version> - </parent> - <artifactId>transport-rest-client</artifactId> - <name>Java Chassis::Transports::Rest::Client</name> +<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" + xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.servicecomb</groupId> + <artifactId>transport-rest</artifactId> + <version>1.0.0-m2-SNAPSHOT</version> + </parent> + <artifactId>transport-rest-client</artifactId> + <name>Java Chassis::Transports::Rest::Client</name> - <dependencies> - <dependency> - <groupId>org.apache.servicecomb</groupId> - <artifactId>foundation-vertx</artifactId> - </dependency> - <dependency> - <groupId>org.apache.servicecomb</groupId> - <artifactId>common-rest</artifactId> - </dependency> - <dependency> - <groupId>org.slf4j</groupId> - <artifactId>slf4j-log4j12</artifactId> - <scope>test</scope> - </dependency> - <dependency> - <groupId>log4j</groupId> - <artifactId>log4j</artifactId> - <scope>test</scope> - </dependency> - </dependencies> + <dependencies> + <dependency> + <groupId>org.apache.servicecomb</groupId> + <artifactId>foundation-vertx</artifactId> + </dependency> + <dependency> + <groupId>org.apache.servicecomb</groupId> + <artifactId>common-rest</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.servicecomb</groupId> + <artifactId>foundation-test-scaffolding</artifactId> + <scope>test</scope> + </dependency> + </dependencies> </project> diff --git a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestTransportClient.java b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestTransportClient.java index 1fed065..937097a 100644 --- a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestTransportClient.java +++ b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestTransportClient.java @@ -17,7 +17,11 @@ package org.apache.servicecomb.transport.rest.client; +import java.util.List; + +import org.apache.servicecomb.common.rest.filter.HttpClientFilter; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.foundation.vertx.VertxTLSBuilder; import org.apache.servicecomb.foundation.vertx.VertxUtils; import org.apache.servicecomb.foundation.vertx.client.ClientPoolManager; @@ -25,7 +29,7 @@ import org.apache.servicecomb.foundation.vertx.client.ClientVerticle; import org.apache.servicecomb.foundation.vertx.client.http.HttpClientPoolFactory; import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext; import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.apache.servicecomb.transport.rest.client.http.VertxHttpMethod; +import org.apache.servicecomb.transport.rest.client.http.RestClientInvocation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,8 +44,11 @@ public final class RestTransportClient { private ClientPoolManager<HttpClientWithContext> clientMgr; + private List<HttpClientFilter> httpClientFilters; public void init(Vertx vertx) throws Exception { + httpClientFilters = SPIServiceUtils.getSortedService(HttpClientFilter.class); + HttpClientOptions httpClientOptions = createHttpClientOptions(); clientMgr = new ClientPoolManager<>(vertx, new HttpClientPoolFactory(httpClientOptions)); @@ -61,11 +68,12 @@ public final class RestTransportClient { return httpClientOptions; } - public void send(Invocation invocation, AsyncResponse asyncResp) throws Exception { + public void send(Invocation invocation, AsyncResponse asyncResp) { HttpClientWithContext httpClientWithContext = clientMgr.findClientPool(invocation.isSync()); + RestClientInvocation restClientInvocation = new RestClientInvocation(httpClientWithContext, httpClientFilters); try { - VertxHttpMethod.INSTANCE.doMethod(httpClientWithContext, invocation, asyncResp); - } catch (Exception e) { + restClientInvocation.invoke(invocation, asyncResp); + } catch (Throwable e) { asyncResp.fail(invocation.getInvocationType(), e); LOGGER.error("vertx rest transport send error.", e); } diff --git a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/VertxHttpMethod.java b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java similarity index 69% rename from transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/VertxHttpMethod.java rename to transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java index d4f2aa1..58789a6 100644 --- a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/VertxHttpMethod.java +++ b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java @@ -29,7 +29,6 @@ import org.apache.servicecomb.core.transport.AbstractTransport; import org.apache.servicecomb.foundation.common.net.IpPort; import org.apache.servicecomb.foundation.common.net.URIEndpointObject; import org.apache.servicecomb.foundation.common.utils.JsonUtils; -import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext; import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx; import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx; @@ -43,33 +42,42 @@ import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; import io.vertx.core.buffer.Buffer; -import io.vertx.core.http.HttpClient; import io.vertx.core.http.HttpClientRequest; import io.vertx.core.http.HttpClientResponse; import io.vertx.core.http.HttpMethod; import io.vertx.core.http.RequestOptions; -public class VertxHttpMethod { - private static final Logger LOGGER = LoggerFactory.getLogger(VertxHttpMethod.class); +public class RestClientInvocation { + private static final Logger LOGGER = LoggerFactory.getLogger(RestClientInvocation.class); - public static final VertxHttpMethod INSTANCE = new VertxHttpMethod(); + private HttpClientWithContext httpClientWithContext; - static List<HttpClientFilter> httpClientFilters = SPIServiceUtils.getSortedService(HttpClientFilter.class); + private Invocation invocation; + + private AsyncResponse asyncResp; + + private List<HttpClientFilter> httpClientFilters; + + private HttpClientRequest clientRequest; + + private HttpClientResponse clientResponse; + + public RestClientInvocation(HttpClientWithContext httpClientWithContext, List<HttpClientFilter> httpClientFilters) { + this.httpClientWithContext = httpClientWithContext; + this.httpClientFilters = httpClientFilters; + } + + public void invoke(Invocation invocation, AsyncResponse asyncResp) throws Exception { + this.invocation = invocation; + this.asyncResp = asyncResp; - public void doMethod(HttpClientWithContext httpClientWithContext, Invocation invocation, - AsyncResponse asyncResp) throws Exception { OperationMeta operationMeta = invocation.getOperationMeta(); RestOperationMeta swaggerRestOperation = operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION); - String path = this.createRequestPath(invocation, swaggerRestOperation); + String path = this.createRequestPath(swaggerRestOperation); IpPort ipPort = (IpPort) invocation.getEndpoint().getAddress(); - HttpClientRequest clientRequest = - this.createRequest(httpClientWithContext.getHttpClient(), - invocation, - ipPort, - path, - asyncResp); + createRequest(ipPort, path); clientRequest.putHeader(org.apache.servicecomb.core.Const.TARGET_MICROSERVICE, invocation.getMicroserviceName()); RestClientRequestImpl restClientRequest = new RestClientRequestImpl(clientRequest, httpClientWithContext.context().owner(), asyncResp); @@ -88,7 +96,7 @@ public class VertxHttpMethod { // 从业务线程转移到网络线程中去发送 httpClientWithContext.runOnContext(httpClient -> { - this.setCseContext(invocation, clientRequest); + this.setCseContext(); clientRequest.setTimeout(AbstractTransport.getRequestTimeoutProperty().get()); try { restClientRequest.end(); @@ -99,15 +107,14 @@ public class VertxHttpMethod { }); } - private HttpMethod getMethod(Invocation invocation) { + private HttpMethod getMethod() { OperationMeta operationMeta = invocation.getOperationMeta(); RestOperationMeta swaggerRestOperation = operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION); String method = swaggerRestOperation.getHttpMethod(); return HttpMethod.valueOf(method); } - HttpClientRequest createRequest(HttpClient client, Invocation invocation, IpPort ipPort, String path, - AsyncResponse asyncResp) { + void createRequest(IpPort ipPort, String path) { URIEndpointObject endpoint = (URIEndpointObject) invocation.getEndpoint().getAddress(); RequestOptions requestOptions = new RequestOptions(); requestOptions.setHost(ipPort.getHostOrIp()) @@ -115,51 +122,51 @@ public class VertxHttpMethod { .setSsl(endpoint.isSslEnabled()) .setURI(path); - HttpMethod method = getMethod(invocation); + HttpMethod method = getMethod(); LOGGER.debug("Sending request by rest, method={}, qualifiedName={}, path={}, endpoint={}.", method, invocation.getMicroserviceQualifiedName(), path, invocation.getEndpoint().getEndpoint()); - HttpClientRequest request = client.request(method, requestOptions, response -> { - handleResponse(invocation, response, asyncResp); - }); - return request; + clientRequest = httpClientWithContext.getHttpClient().request(method, requestOptions, this::handleResponse); } - void handleResponse(Invocation invocation, HttpClientResponse clientResponse, - AsyncResponse asyncResp) { + protected void handleResponse(HttpClientResponse httpClientResponse) { + this.clientResponse = httpClientResponse; + clientResponse.bodyHandler(responseBuf -> { - // 此时是在网络线程中,不应该就地处理,通过dispatcher转移线程 - invocation.getResponseExecutor().execute(() -> { - try { - HttpServletResponseEx responseEx = - new VertxClientResponseToHttpServletResponse(clientResponse, responseBuf); - for (HttpClientFilter filter : httpClientFilters) { - Response response = filter.afterReceiveResponse(invocation, responseEx); - if (response != null) { - asyncResp.complete(response); - return; - } + processResponseBody(responseBuf); + }); + } + + protected void processResponseBody(Buffer responseBuf) { + invocation.getResponseExecutor().execute(() -> { + try { + HttpServletResponseEx responseEx = + new VertxClientResponseToHttpServletResponse(clientResponse, responseBuf); + for (HttpClientFilter filter : httpClientFilters) { + Response response = filter.afterReceiveResponse(invocation, responseEx); + if (response != null) { + asyncResp.complete(response); + return; } - } catch (Throwable e) { - asyncResp.fail(invocation.getInvocationType(), e); } - }); + } catch (Throwable e) { + asyncResp.fail(invocation.getInvocationType(), e); + } }); } - protected void setCseContext(Invocation invocation, HttpClientRequest request) { + protected void setCseContext() { try { String cseContext = JsonUtils.writeValueAsString(invocation.getContext()); - request.putHeader(org.apache.servicecomb.core.Const.CSE_CONTEXT, cseContext); + clientRequest.putHeader(org.apache.servicecomb.core.Const.CSE_CONTEXT, cseContext); } catch (Exception e) { - LOGGER.debug(e.toString()); + LOGGER.debug("Failed to encode and set cseContext.", e); } } - protected String createRequestPath(Invocation invocation, - RestOperationMeta swaggerRestOperation) throws Exception { + protected String createRequestPath(RestOperationMeta swaggerRestOperation) throws Exception { URIEndpointObject address = (URIEndpointObject) invocation.getEndpoint().getAddress(); String urlPrefix = address.getFirst(Const.URL_PREFIX); diff --git a/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/http/TestRestClientInvocation.java b/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/http/TestRestClientInvocation.java new file mode 100644 index 0000000..5b5f4a1 --- /dev/null +++ b/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/http/TestRestClientInvocation.java @@ -0,0 +1,302 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.transport.rest.client.http; + +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Level; +import org.apache.servicecomb.common.rest.RestConst; +import org.apache.servicecomb.common.rest.definition.RestOperationMeta; +import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder; +import org.apache.servicecomb.common.rest.filter.HttpClientFilter; +import org.apache.servicecomb.core.Endpoint; +import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.core.executor.ReactiveExecutor; +import org.apache.servicecomb.foundation.common.net.URIEndpointObject; +import org.apache.servicecomb.foundation.test.scaffolding.log.LogCollector; +import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext; +import org.apache.servicecomb.serviceregistry.api.Const; +import org.apache.servicecomb.swagger.invocation.AsyncResponse; +import org.apache.servicecomb.swagger.invocation.Response; +import org.apache.servicecomb.swagger.invocation.exception.InvocationException; +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import io.vertx.core.Context; +import io.vertx.core.Handler; +import io.vertx.core.buffer.Buffer; +import io.vertx.core.http.HttpClient; +import io.vertx.core.http.HttpClientRequest; +import io.vertx.core.http.HttpClientResponse; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.http.RequestOptions; +import mockit.Deencapsulation; +import mockit.Mock; +import mockit.MockUp; +import mockit.Mocked; + +public class TestRestClientInvocation { + Handler<Throwable> exceptionHandler; + + Handler<Buffer> bodyHandler; + + Map<String, String> headers = new HashMap<>(); + + HttpClientRequest request = mock(HttpClientRequest.class); + + HttpClient httpClient = mock(HttpClient.class); + + Context context = mock(Context.class); + + HttpClientWithContext httpClientWithContext = new HttpClientWithContext(httpClient, context); + + Invocation invocation = mock(Invocation.class); + + Response response; + + AsyncResponse asyncResp = resp -> { + response = resp; + }; + + OperationMeta operationMeta = mock(OperationMeta.class); + + Endpoint endpoint = mock(Endpoint.class); + + RestOperationMeta swaggerRestOperation = mock(RestOperationMeta.class); + + URLPathBuilder urlPathBuilder = mock(URLPathBuilder.class); + + URIEndpointObject address = mock(URIEndpointObject.class); + + List<HttpClientFilter> httpClientFilters = new ArrayList<>(); + + RestClientInvocation restClientInvocation = new RestClientInvocation(httpClientWithContext, httpClientFilters); + + Map<String, Object> handlerContext = new HashMap<>(); + + @SuppressWarnings("unchecked") + @Before + public void setup() { + Deencapsulation.setField(restClientInvocation, "clientRequest", request); + Deencapsulation.setField(restClientInvocation, "invocation", invocation); + Deencapsulation.setField(restClientInvocation, "asyncResp", asyncResp); + + when(invocation.getOperationMeta()).thenReturn(operationMeta); + when(swaggerRestOperation.getPathBuilder()).thenReturn(urlPathBuilder); + when(swaggerRestOperation.getHttpMethod()).thenReturn("GET"); + when(operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION)).thenReturn(swaggerRestOperation); + when(invocation.getEndpoint()).thenReturn(endpoint); + when(endpoint.getAddress()).thenReturn(address); + when(invocation.getHandlerContext()).then(answer -> handlerContext); + when(httpClient.request((HttpMethod) Mockito.any(), (RequestOptions) Mockito.any(), Mockito.any())) + .thenReturn(request); + doAnswer(a -> { + exceptionHandler = (Handler<Throwable>) a.getArguments()[0]; + return request; + }).when(request).exceptionHandler(any()); + doAnswer(a -> { + headers.put(a.getArgumentAt(0, String.class), a.getArgumentAt(1, String.class)); + return request; + }).when(request).putHeader((String) any(), (String) any()); + doAnswer(a -> { + ((Handler<Void>) a.getArguments()[0]).handle(null); + return null; + }).when(context).runOnContext(any()); + } + + @Test + public void invoke(@Mocked Response resp) throws Exception { + doAnswer(a -> { + asyncResp.complete(resp); + return null; + }).when(request).end(); + restClientInvocation.invoke(invocation, asyncResp); + + Assert.assertSame(resp, response); + } + + @Test + public void invoke_endThrow() throws Exception { + Mockito.doThrow(Error.class).when(request).end(); + restClientInvocation.invoke(invocation, asyncResp); + + Assert.assertThat(((InvocationException) response.getResult()).getCause(), Matchers.instanceOf(Error.class)); + } + + @Test + public void invoke_requestThrow() throws Exception { + Throwable t = new Error(); + doAnswer(a -> { + exceptionHandler.handle(t); + return null; + }).when(request).end(); + restClientInvocation.invoke(invocation, asyncResp); + restClientInvocation.invoke(invocation, asyncResp); + + Assert.assertThat(((InvocationException) response.getResult()).getCause(), Matchers.sameInstance(t)); + } + + @Test + public void testSetCseContext() { + Map<String, String> contextMap = Collections.singletonMap("k", "v"); + when(invocation.getContext()).thenReturn(contextMap); + + restClientInvocation.setCseContext(); + + Assert.assertEquals("{x-cse-context={\"k\":\"v\"}}", headers.toString()); + } + + @Test + public void testSetCseContext_failed() { + LogCollector logCollector = new LogCollector(); + logCollector.setLogLevel(RestClientInvocation.class.getName(), Level.DEBUG); + Deencapsulation.setField(restClientInvocation, "invocation", null); + + restClientInvocation.setCseContext(); + + Assert.assertEquals("Failed to encode and set cseContext.", logCollector.getEvents().get(0).getMessage()); + logCollector.teardown(); + } + + @SuppressWarnings("unchecked") + @Test + public void handleResponse() { + HttpClientResponse httpClientResponse = mock(HttpClientResponse.class); + doAnswer(a -> { + bodyHandler = (Handler<Buffer>) a.getArguments()[0]; + return httpClientResponse; + }).when(httpClientResponse).bodyHandler(any()); + + Buffer buf = Buffer.buffer(); + new MockUp<RestClientInvocation>(restClientInvocation) { + @Mock + void processResponseBody(Buffer responseBuf) { + asyncResp.success(buf); + } + }; + + restClientInvocation.handleResponse(httpClientResponse); + bodyHandler.handle(buf); + + Assert.assertSame(buf, response.getResult()); + } + + @Test + public void processResponseBody() { + Response resp = Response.ok(null); + + HttpClientResponse httpClientResponse = mock(HttpClientResponse.class); + Deencapsulation.setField(restClientInvocation, "clientResponse", httpClientResponse); + + { + HttpClientFilter filter = mock(HttpClientFilter.class); + when(filter.afterReceiveResponse(any(), any())).thenReturn(null); + httpClientFilters.add(filter); + } + { + HttpClientFilter filter = mock(HttpClientFilter.class); + when(filter.afterReceiveResponse(any(), any())).thenReturn(resp); + httpClientFilters.add(filter); + } + + when(invocation.getResponseExecutor()).thenReturn(new ReactiveExecutor()); + + restClientInvocation.processResponseBody(null); + + Assert.assertSame(resp, response); + } + + @SuppressWarnings("unchecked") + @Test + public void processResponseBody_throw() { + HttpClientResponse httpClientResponse = mock(HttpClientResponse.class); + Deencapsulation.setField(restClientInvocation, "clientResponse", httpClientResponse); + + { + HttpClientFilter filter = mock(HttpClientFilter.class); + when(filter.afterReceiveResponse(any(), any())).thenThrow(Error.class); + httpClientFilters.add(filter); + } + + when(invocation.getResponseExecutor()).thenReturn(new ReactiveExecutor()); + + restClientInvocation.processResponseBody(null); + + Assert.assertThat(((InvocationException) response.getResult()).getCause(), Matchers.instanceOf(Error.class)); + } + + @Test + public void createRequestPath_NoUrlPrefixNoPath() throws Exception { + when(address.getFirst(Const.URL_PREFIX)).thenReturn(null); + + when(urlPathBuilder.createRequestPath(any())).thenReturn("/path"); + + String path = restClientInvocation.createRequestPath(swaggerRestOperation); + Assert.assertEquals("/path", path); + } + + @Test + public void createRequestPath_noUrlPrefixHavePath() throws Exception { + handlerContext.put(RestConst.REST_CLIENT_REQUEST_PATH, "/client/path"); + when(address.getFirst(Const.URL_PREFIX)).thenReturn(null); + + String path = restClientInvocation.createRequestPath(swaggerRestOperation); + Assert.assertEquals("/client/path", path); + } + + @Test + public void createRequestPath_haveUrlPrefixNoPath() throws Exception { + when(address.getFirst(Const.URL_PREFIX)).thenReturn("/prefix"); + + when(urlPathBuilder.createRequestPath(any())).thenReturn("/path"); + + String path = restClientInvocation.createRequestPath(swaggerRestOperation); + Assert.assertEquals("/prefix/path", path); + } + + @Test + public void createRequestPath_haveUrlPrefixHavePath() throws Exception { + when(address.getFirst(Const.URL_PREFIX)).thenReturn("/prefix"); + handlerContext.put(RestConst.REST_CLIENT_REQUEST_PATH, "/client/path"); + + String path = restClientInvocation.createRequestPath(swaggerRestOperation); + Assert.assertEquals("/prefix/client/path", path); + } + + @Test + public void createRequestPath_haveUrlPrefixHavePathAndStartWith() throws Exception { + when(address.getFirst(Const.URL_PREFIX)).thenReturn("/prefix"); + handlerContext.put(RestConst.REST_CLIENT_REQUEST_PATH, "/prefix/client/path"); + + String path = restClientInvocation.createRequestPath(swaggerRestOperation); + Assert.assertEquals("/prefix/client/path", path); + } +} diff --git a/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/http/TestVertxHttpMethod.java b/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/http/TestVertxHttpMethod.java deleted file mode 100644 index 1c9dcfe..0000000 --- a/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/http/TestVertxHttpMethod.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.servicecomb.transport.rest.client.http; - -import static org.junit.Assert.fail; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.servicecomb.common.rest.RestConst; -import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor; -import org.apache.servicecomb.common.rest.definition.RestOperationMeta; -import org.apache.servicecomb.common.rest.definition.path.URLPathBuilder; -import org.apache.servicecomb.core.Endpoint; -import org.apache.servicecomb.core.Invocation; -import org.apache.servicecomb.core.definition.OperationMeta; -import org.apache.servicecomb.foundation.common.net.IpPort; -import org.apache.servicecomb.foundation.common.net.URIEndpointObject; -import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext; -import org.apache.servicecomb.serviceregistry.api.Const; -import org.apache.servicecomb.swagger.invocation.AsyncResponse; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -import io.vertx.core.Context; -import io.vertx.core.Handler; -import io.vertx.core.http.HttpClient; -import io.vertx.core.http.HttpClientRequest; -import io.vertx.core.http.HttpClientResponse; -import io.vertx.core.http.HttpMethod; -import mockit.Expectations; -import mockit.Injectable; -import mockit.Mock; -import mockit.MockUp; -import mockit.Mocked; - -public class TestVertxHttpMethod extends VertxHttpMethod { - - HttpClientRequest request; - - @Before - public void setup() { - request = mock(HttpClientRequest.class); - } - - @Test - public void testDoMethodNullPointerException(@Mocked HttpClient httpClient) throws Exception { - Context context = new MockUp<Context>() { - @Mock - public void runOnContext(Handler<Void> action) { - action.handle(null); - } - }.getMockInstance(); - HttpClientWithContext httpClientWithContext = new HttpClientWithContext(httpClient, context); - - Invocation invocation = mock(Invocation.class); - AsyncResponse asyncResp = mock(AsyncResponse.class); - - try { - this.doMethod(httpClientWithContext, invocation, asyncResp); - fail("Expect to throw NullPointerException, but got none"); - } catch (NullPointerException e) { - } - } - - @Test - public void testDoMethod(@Mocked HttpClient httpClient, @Injectable URIEndpointObject address) throws Exception { - Context context = new MockUp<Context>() { - @Mock - public void runOnContext(Handler<Void> action) { - action.handle(null); - } - }.getMockInstance(); - HttpClientWithContext httpClientWithContext = new HttpClientWithContext(httpClient, context); - - Invocation invocation = mock(Invocation.class); - AsyncResponse asyncResp = mock(AsyncResponse.class); - OperationMeta operationMeta = mock(OperationMeta.class); - RestOperationMeta swaggerRestOperation = mock(RestOperationMeta.class); - - Endpoint endpoint = mock(Endpoint.class); - when(invocation.getOperationMeta()).thenReturn(operationMeta); - URLPathBuilder urlPathBuilder = mock(URLPathBuilder.class); - when(swaggerRestOperation.getPathBuilder()).thenReturn(urlPathBuilder); - operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION); - when(operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION)).thenReturn(swaggerRestOperation); - when(invocation.getEndpoint()).thenReturn(endpoint); - when(endpoint.getAddress()).thenReturn(address); - - when(request.exceptionHandler(Mockito.any())).then(answer -> null); - Map<String, Object> map = new HashMap<>(); - when(invocation.getHandlerContext()).then(answer -> map);; - - this.doMethod(httpClientWithContext, invocation, asyncResp); - Assert.assertTrue(true); - } - - @Test - public void testCreateRequest() { - HttpClient client = mock(HttpClient.class); - Invocation invocation = mock(Invocation.class); - OperationMeta operationMeta = mock(OperationMeta.class); - Endpoint endpoint = mock(Endpoint.class); - URIEndpointObject address = mock(URIEndpointObject.class); - when(invocation.getEndpoint()).thenReturn(endpoint); - when(endpoint.getAddress()).thenReturn(address); - when(address.isSslEnabled()).thenReturn(false); - when(invocation.getOperationMeta()).thenReturn(operationMeta); - RestOperationMeta swaggerRestOperation = mock(RestOperationMeta.class); - when(operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION)).thenReturn(swaggerRestOperation); - IpPort ipPort = mock(IpPort.class); - when(ipPort.getPort()).thenReturn(10); - when(ipPort.getHostOrIp()).thenReturn("ever"); - AsyncResponse asyncResp = mock(AsyncResponse.class); - List<HttpMethod> methods = new ArrayList<>( - Arrays.asList(HttpMethod.GET, HttpMethod.PUT, HttpMethod.POST, HttpMethod.DELETE, HttpMethod.PATCH)); - for (HttpMethod method : methods) { - when(swaggerRestOperation.getHttpMethod()).thenReturn(method.toString()); - HttpClientRequest obj = - VertxHttpMethod.INSTANCE.createRequest(client, invocation, ipPort, "good", asyncResp); - Assert.assertNull(obj); - } - } - - @Test - public void testSetCseContext() { - boolean status = false; - try { - Invocation invocation = mock(Invocation.class); - HttpClientResponse httpResponse = mock(HttpClientResponse.class); - OperationMeta operationMeta = mock(OperationMeta.class); - RestOperationMeta swaggerRestOperation = mock(RestOperationMeta.class); - HttpClientRequest request = mock(HttpClientRequest.class); - - Endpoint endpoint = mock(Endpoint.class); - when(invocation.getOperationMeta()).thenReturn(operationMeta); - URLPathBuilder urlPathBuilder = mock(URLPathBuilder.class); - when(swaggerRestOperation.getPathBuilder()).thenReturn(urlPathBuilder); - operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION); - when(operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION)).thenReturn(swaggerRestOperation); - when(invocation.getEndpoint()).thenReturn(endpoint); - String contentType = httpResponse.getHeader("Content-Type"); - ProduceProcessor produceProcessor = mock(ProduceProcessor.class); - when(swaggerRestOperation.findProduceProcessor(contentType)).thenReturn(produceProcessor); - this.setCseContext(invocation, request); - } catch (Exception ex) { - status = true; - } - Assert.assertFalse(status); - } - - @Test - public void testHandleResponse() { - boolean status = false; - try { - Invocation invocation = mock(Invocation.class); - AsyncResponse asyncResp = mock(AsyncResponse.class); - HttpClientResponse httpResponse = mock(HttpClientResponse.class); - OperationMeta operationMeta = mock(OperationMeta.class); - RestOperationMeta swaggerRestOperation = mock(RestOperationMeta.class); - - Endpoint endpoint = mock(Endpoint.class); - when(invocation.getOperationMeta()).thenReturn(operationMeta); - URLPathBuilder urlPathBuilder = mock(URLPathBuilder.class); - when(swaggerRestOperation.getPathBuilder()).thenReturn(urlPathBuilder); - operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION); - when(operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION)).thenReturn(swaggerRestOperation); - when(invocation.getEndpoint()).thenReturn(endpoint); - - String contentType = httpResponse.getHeader("Content-Type"); - ProduceProcessor produceProcessor = mock(ProduceProcessor.class); - when(swaggerRestOperation.findProduceProcessor(contentType)).thenReturn(produceProcessor); - this.handleResponse(invocation, httpResponse, asyncResp); - } catch (Exception ex) { - status = true; - } - Assert.assertFalse(status); - } - - @Override - protected HttpClientRequest createRequest(HttpClient client, Invocation invocation, IpPort ipPort, String path, - AsyncResponse asyncResp) { - return request; - } - - @Test - public void testCreateRequestPathNoUrlPrefixNoPath(@Injectable Invocation invocation, - @Injectable RestOperationMeta swaggerRestOperation, @Injectable Endpoint endpoint, - @Injectable URIEndpointObject address, @Injectable URLPathBuilder builder) throws Exception { - new Expectations() { - { - endpoint.getAddress(); - result = address; - builder.createRequestPath((Object[]) any); - result = "/path"; - } - }; - String path = this.createRequestPath(invocation, swaggerRestOperation); - Assert.assertEquals("/path", path); - } - - @Test - public void testCreateRequestPathNoUrlPrefixHavePath(@Injectable Invocation invocation, - @Injectable RestOperationMeta swaggerRestOperation, @Injectable Endpoint endpoint, - @Injectable URIEndpointObject address, @Injectable URLPathBuilder builder) throws Exception { - Map<String, Object> contextMap = new HashMap<>(); - contextMap.put(RestConst.REST_CLIENT_REQUEST_PATH, "/client/path"); - - new Expectations() { - { - endpoint.getAddress(); - result = address; - invocation.getHandlerContext(); - result = contextMap; - } - }; - String path = this.createRequestPath(invocation, swaggerRestOperation); - Assert.assertEquals("/client/path", path); - } - - @Test - public void testCreateRequestPathHaveUrlPrefixNoPath(@Injectable Invocation invocation, - @Injectable RestOperationMeta swaggerRestOperation, @Injectable Endpoint endpoint, - @Injectable URIEndpointObject address, @Injectable URLPathBuilder builder) throws Exception { - new Expectations() { - { - endpoint.getAddress(); - result = address; - address.getFirst(Const.URL_PREFIX); - result = "/root"; - builder.createRequestPath((Object[]) any); - result = "/path"; - } - }; - String path = this.createRequestPath(invocation, swaggerRestOperation); - Assert.assertEquals("/root/path", path); - } - - @Test - public void testCreateRequestPathHaveUrlPrefixHavePath(@Injectable Invocation invocation, - @Injectable RestOperationMeta swaggerRestOperation, @Injectable Endpoint endpoint, - @Injectable URIEndpointObject address, @Injectable URLPathBuilder builder) throws Exception { - Map<String, Object> contextMap = new HashMap<>(); - contextMap.put(RestConst.REST_CLIENT_REQUEST_PATH, "/client/path"); - - new Expectations() { - { - endpoint.getAddress(); - result = address; - address.getFirst(Const.URL_PREFIX); - result = "/root"; - invocation.getHandlerContext(); - result = contextMap; - } - }; - String path = this.createRequestPath(invocation, swaggerRestOperation); - Assert.assertEquals("/root/client/path", path); - } - - @Test - public void testCreateRequestPathHaveUrlPrefixHavePathAndStartWith(@Injectable Invocation invocation, - @Injectable RestOperationMeta swaggerRestOperation, @Injectable Endpoint endpoint, - @Injectable URIEndpointObject address, @Injectable URLPathBuilder builder) throws Exception { - Map<String, Object> contextMap = new HashMap<>(); - contextMap.put(RestConst.REST_CLIENT_REQUEST_PATH, "/client/path"); - - new Expectations() { - { - endpoint.getAddress(); - result = address; - address.getFirst(Const.URL_PREFIX); - result = "/client"; - invocation.getHandlerContext(); - result = contextMap; - } - }; - String path = this.createRequestPath(invocation, swaggerRestOperation); - Assert.assertEquals("/client/path", path); - } -} -- To stop receiving notification emails like this one, please contact [email protected].
