You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2018/08/01 10:10:19 UTC
[incubator-servicecomb-java-chassis] 05/06: [SCB-790] create base
integration test mechanism,
and base test case: 1.deploy edge 2.deploy standalone producer 3.run test
case with different consumer/transport/producer combination 4.stop producer
5.stop edge
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 5cfc19af59eaefa8767ba3413d021ee42f763bdb
Author: wujimin <wu...@huawei.com>
AuthorDate: Tue Jul 31 11:36:27 2018 +0800
[SCB-790] create base integration test mechanism, and base test case:
1.deploy edge
2.deploy standalone producer
3.run test case with different consumer/transport/producer combination
4.stop producer
5.stop edge
---
integration-tests/it-common-service/enable-it-jar | 0
integration-tests/it-common-service/pom.xml | 41 +++++
.../apache/servicecomb/it/CommonServiceMain.java | 23 +++
integration-tests/it-common/enable-it-jar | 0
integration-tests/it-common/pom.xml | 37 ++++
.../org/apache/servicecomb/it/CommandReceiver.java | 97 ++++++++++
.../org/apache/servicecomb/it/ITBootListener.java | 82 +++++++++
.../java/org/apache/servicecomb/it/ITMain.java | 27 +++
.../java/org/apache/servicecomb/it/ITUtils.java | 123 +++++++++++++
.../it-common/src/main/resources/logback.xml | 29 +++
.../it-common/src/main/resources/microservice.yaml | 46 +++++
integration-tests/it-consumer/pom.xml | 46 +++++
.../org/apache/servicecomb/it/ConsumerMain.java | 135 ++++++++++++++
.../org/apache/servicecomb/it/ResultPrinter.java | 65 +++++++
.../servicecomb/it/deploy/DeployDefinition.java | 86 +++++++++
.../org/apache/servicecomb/it/deploy/Deploys.java | 192 ++++++++++++++++++++
.../servicecomb/it/deploy/MicroserviceDeploy.java | 71 ++++++++
.../it/deploy/MicroserviceDeployDefinition.java | 56 ++++++
.../apache/servicecomb/it/deploy/NormalDeploy.java | 114 ++++++++++++
.../servicecomb/it/deploy/SubProcessLogger.java | 68 +++++++
.../it/extend/engine/ITClientHttpRequest.java | 43 +++++
.../extend/engine/ITClientHttpRequestFactory.java | 36 ++++
.../servicecomb/it/extend/engine/ITInvoker.java | 69 ++++++++
.../apache/servicecomb/it/junit/ITJUnitUtils.java | 102 +++++++++++
.../apache/servicecomb/it/junit/SCBFailure.java | 37 ++++
.../it/testcase/base/TestDataTypePojo.java | 66 +++++++
.../it/testcase/base/TestDataTypeRest.java | 94 ++++++++++
.../servicecomb/it/testcase/base/TestDownload.java | 142 +++++++++++++++
.../servicecomb/it/testcase/base/TestGeneric.java | 26 +++
.../it/testcase/support/DataTypePojoIntf.java | 22 +++
.../it/testcase/support/DataTypeRestIntf.java | 30 ++++
.../it/testcase/support/DownloadSchemaIntf.java | 39 +++++
.../it/testcase/support/ProducerDevMode.java | 22 +++
.../src/main/resources/microservice.yaml | 19 ++
.../java/org/apache/servicecomb/it/TestMain.java | 30 ++++
integration-tests/it-edge/enable-it-jar | 0
integration-tests/it-edge/pom.xml | 53 ++++++
.../apache/servicecomb/it/authentication/Auth.java | 24 +++
.../servicecomb/it/authentication/encrypt/Hcr.java | 39 +++++
.../org/apache/servicecomb/it/edge/EdgeConst.java | 20 +++
.../apache/servicecomb/it/edge/EdgeDispatcher.java | 58 ++++++
.../org/apache/servicecomb/it/edge/EdgeMain.java | 26 +++
.../servicecomb/it/edge/encrypt/Encrypt.java | 28 +++
.../it/edge/encrypt/EncryptContext.java | 46 +++++
.../it/edge/encrypt/EncryptEdgeDispatcher.java | 114 ++++++++++++
.../it/edge/encrypt/EncryptEdgeInvocation.java | 34 ++++
.../it/edge/encrypt/filter/DecodeBodyFilter.java | 66 +++++++
.../encrypt/filter/EdgeSignatureRequestFilter.java | 67 +++++++
.../filter/EdgeSignatureResponseFilter.java | 76 ++++++++
.../it/edge/encrypt/filter/UserIdFilter.java | 46 +++++
.../servicecomb/it/edge/handler/AuthHandler.java | 74 ++++++++
...servicecomb.common.rest.filter.HttpServerFilter | 21 +++
...cecomb.transport.rest.vertx.VertxHttpDispatcher | 19 ++
.../src/main/resources/config/cse.handler.xml | 20 +++
.../it-edge/src/main/resources/microservice.yaml | 48 +++++
integration-tests/it-producer/enable-it-jar | 0
integration-tests/it-producer/pom.xml | 41 +++++
.../apache/servicecomb/it/BaseProducerMain.java | 23 +++
.../servicecomb/it/schema/DataTypeJaxrs.java | 74 ++++++++
.../apache/servicecomb/it/schema/DataTypePojo.java | 42 +++++
.../servicecomb/it/schema/DataTypeSpringmvc.java | 64 +++++++
.../servicecomb/it/schema/DownloadSchema.java | 195 +++++++++++++++++++++
.../src/main/resources/microservice.yaml | 20 +++
integration-tests/pom.xml | 35 ++++
64 files changed, 3488 insertions(+)
diff --git a/integration-tests/it-common-service/enable-it-jar b/integration-tests/it-common-service/enable-it-jar
new file mode 100644
index 0000000..e69de29
diff --git a/integration-tests/it-common-service/pom.xml b/integration-tests/it-common-service/pom.xml
new file mode 100644
index 0000000..48ac9f0
--- /dev/null
+++ b/integration-tests/it-common-service/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>integration-tests</artifactId>
+ <groupId>org.apache.servicecomb.tests</groupId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>it-common-service</artifactId>
+ <name>Java Chassis::IT::CommonService</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.servicecomb.tests</groupId>
+ <artifactId>it-common</artifactId>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <it.main>org.apache.servicecomb.it.CommonServiceMain</it.main>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/integration-tests/it-common-service/src/main/java/org/apache/servicecomb/it/CommonServiceMain.java b/integration-tests/it-common-service/src/main/java/org/apache/servicecomb/it/CommonServiceMain.java
new file mode 100644
index 0000000..7dfb147
--- /dev/null
+++ b/integration-tests/it-common-service/src/main/java/org/apache/servicecomb/it/CommonServiceMain.java
@@ -0,0 +1,23 @@
+/*
+ * 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.it;
+
+public class CommonServiceMain {
+ public static void main(String[] args) {
+ ITMain.main(args);
+ }
+}
diff --git a/integration-tests/it-common/enable-it-jar b/integration-tests/it-common/enable-it-jar
new file mode 100644
index 0000000..e69de29
diff --git a/integration-tests/it-common/pom.xml b/integration-tests/it-common/pom.xml
new file mode 100644
index 0000000..653b800
--- /dev/null
+++ b/integration-tests/it-common/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>integration-tests</artifactId>
+ <groupId>org.apache.servicecomb.tests</groupId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>it-common</artifactId>
+ <name>Java Chassis::IT::Common</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/CommandReceiver.java b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/CommandReceiver.java
new file mode 100644
index 0000000..08c6bbb
--- /dev/null
+++ b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/CommandReceiver.java
@@ -0,0 +1,97 @@
+/*
+ * 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.it;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.SCBStatus;
+import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.TextNode;
+
+public class CommandReceiver {
+ private static final Logger LOGGER = LoggerFactory.getLogger(CommandReceiver.class);
+
+ public CommandReceiver() {
+ Thread thread = new Thread(this::run, "it-command-receiver");
+ thread.setDaemon(true);
+ thread.start();
+ }
+
+ public void run() {
+ try {
+ doRun();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void doRun() throws IOException {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ try {
+ JsonNode cmd = JsonUtils.OBJ_MAPPER.readTree(line);
+ dispatchCommand(cmd);
+ } catch (Throwable e) {
+ LOGGER.error("Failed to execute command: {}", line, e);
+ }
+ }
+ reader.close();
+ }
+
+ private void dispatchCommand(JsonNode cmd) {
+ LOGGER.info("dispatch command: {}", cmd);
+ if (TextNode.class.isInstance(cmd)) {
+ onStringCommand(cmd.asText());
+ return;
+ }
+
+ throw new UnsupportedOperationException(cmd.toString());
+ }
+
+ protected void onStringCommand(String command) {
+ switch (command) {
+ case "ms-stop":
+ stop();
+ break;
+ default:
+ throw new UnsupportedOperationException(command);
+ }
+ }
+
+ protected void stop() {
+ new Thread(() -> {
+ for (; ; ) {
+ SCBEngine.getInstance().destroy();
+ if (ITBootListener.isDone() && SCBStatus.DOWN.equals(SCBEngine.getInstance().getStatus())) {
+ LOGGER.info("succeed to close " + RegistryUtils.getMicroservice().getServiceName());
+ break;
+ }
+ ITUtils.forceWait(TimeUnit.SECONDS, 1);
+ }
+ }, "it-stop").start();
+ }
+}
diff --git a/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITBootListener.java b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITBootListener.java
new file mode 100644
index 0000000..185fb80
--- /dev/null
+++ b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITBootListener.java
@@ -0,0 +1,82 @@
+/*
+ * 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.it;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.servicecomb.core.BootListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.netflix.config.ConcurrentCompositeConfiguration;
+import com.netflix.config.DynamicPropertyFactory;
+
+@Component
+public class ITBootListener implements BootListener {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ITBootListener.class);
+
+ private static boolean done;
+
+ public static boolean isDone() {
+ return done;
+ }
+
+ @Override
+ public void onBootEvent(BootEvent event) {
+ if (!EventType.BEFORE_HANDLER.equals(event.getEventType())) {
+ return;
+ }
+
+ selectPort("servicecomb.rest.address");
+ selectPort("servicecomb.highway.address");
+ done = true;
+ }
+
+ protected void selectPort(String cfgKey) {
+ String endpoint = DynamicPropertyFactory.getInstance().getStringProperty(cfgKey, null).get();
+ if (endpoint == null) {
+ return;
+ }
+
+ URI uri = URI.create("http://" + endpoint);
+ if (uri.getPort() == 0) {
+ int port = getRandomPort();
+ try {
+ ConcurrentCompositeConfiguration config = (ConcurrentCompositeConfiguration) DynamicPropertyFactory
+ .getBackingConfigurationSource();
+ endpoint = new URIBuilder("http://" + endpoint).setPort(port).build().toString().substring(7);
+ config.getConfiguration(0).setProperty(cfgKey, endpoint);
+ LOGGER.info("change {} to {}.", cfgKey, endpoint);
+ } catch (URISyntaxException e) {
+ throw new IllegalStateException("Failed to build endpoint.", e);
+ }
+ }
+ }
+
+ protected int getRandomPort() {
+ try (ServerSocket serverSocket = new ServerSocket(0)) {
+ return serverSocket.getLocalPort();
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to get random port.", e);
+ }
+ }
+}
diff --git a/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITMain.java b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITMain.java
new file mode 100644
index 0000000..7be9a46
--- /dev/null
+++ b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITMain.java
@@ -0,0 +1,27 @@
+/*
+ * 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.it;
+
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+
+public class ITMain {
+ public static void main(String[] args) {
+ new CommandReceiver();
+
+ BeanUtils.init();
+ }
+}
diff --git a/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITUtils.java b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITUtils.java
new file mode 100644
index 0000000..ada728b
--- /dev/null
+++ b/integration-tests/it-common/src/main/java/org/apache/servicecomb/it/ITUtils.java
@@ -0,0 +1,123 @@
+/*
+ * 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.it;
+
+import java.util.Comparator;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang3.reflect.MethodUtils;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.core.SCBStatus;
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.api.registry.MicroserviceInstance;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersionRule;
+import org.apache.servicecomb.serviceregistry.task.event.PeriodicPullEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class ITUtils {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ITUtils.class);
+
+ private ITUtils() {
+ }
+
+ public static void forceWait(TimeUnit timeUnit, long timeout) {
+ try {
+ timeUnit.sleep(timeout);
+ } catch (InterruptedException e) {
+ // eat the exception
+ }
+ }
+
+ public static void waitBootFinished() {
+ for (; ; ) {
+ if (SCBEngine.getInstance().getStatus().equals(SCBStatus.UP)) {
+ return;
+ }
+
+ forceWait(TimeUnit.MILLISECONDS, 100);
+ }
+ }
+
+ public static Map<String, MicroserviceInstance> waitMicroserviceReadyAndLimit(String appId, String microserviceName,
+ String strVersionRule, int minInstanceCount) {
+ Map<String, MicroserviceInstance> instances = waitMicroserviceReady(appId,
+ microserviceName,
+ strVersionRule,
+ minInstanceCount);
+ return instances.values()
+ .stream()
+ .sorted(Comparator.comparing(MicroserviceInstance::getInstanceId))
+ .limit(minInstanceCount)
+ .collect(Collectors.toMap(MicroserviceInstance::getInstanceId, Function.identity()));
+ }
+
+ public static Map<String, MicroserviceInstance> waitMicroserviceReady(String appId, String microserviceName,
+ String strVersionRule, int minInstanceCount) {
+ LOGGER.info("waiting for microservice online. appId={}, name={}, minInstanceCount={}",
+ appId,
+ microserviceName,
+ minInstanceCount);
+
+ Map<String, MicroserviceInstance> instances;
+ for (;;) {
+ MicroserviceVersionRule microserviceVersionRule = RegistryUtils.getServiceRegistry()
+ .getAppManager()
+ .getOrCreateMicroserviceVersionRule(appId, microserviceName, strVersionRule);
+ instances = microserviceVersionRule.getInstances();
+ if (instances.size() >= minInstanceCount) {
+ break;
+ }
+
+ LOGGER.info(
+ "waiting for microservice online. appId={}, name={}, expect minInstanceCount={}, real instanceCount={}.",
+ appId,
+ microserviceName,
+ minInstanceCount,
+ instances.size());
+ // pull at once
+ EventManager.getEventBus().post(new PeriodicPullEvent());
+ forceWait(TimeUnit.SECONDS, 1);
+ }
+
+ LOGGER.info("microservice already online. appId={}, name={}, instanceCount={}",
+ appId,
+ microserviceName,
+ minInstanceCount);
+ return instances;
+ }
+
+ public static void invokeExactStaticMethod(final Class<?>[] classes, final String methodName, Object... args) {
+ for (Class<?> cls : classes) {
+ invokeExactStaticMethod(cls, methodName, args);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> T invokeExactStaticMethod(final Class<?> cls, final String methodName, Object... args) {
+ try {
+ return (T) MethodUtils.invokeExactStaticMethod(cls, methodName, args);
+ } catch (Throwable e) {
+ throw new IllegalStateException(String.format("Failed to invoke, class=%s, method=%s", cls.getName(), methodName),
+ e);
+ }
+ }
+}
diff --git a/integration-tests/it-common/src/main/resources/logback.xml b/integration-tests/it-common/src/main/resources/logback.xml
new file mode 100644
index 0000000..dfdfa92
--- /dev/null
+++ b/integration-tests/it-common/src/main/resources/logback.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<configuration scan="true">
+ <jmxConfigurator/>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d [%level] [%thread] - %msg (%F:%L\)%n</pattern>
+ </encoder>
+ </appender>
+ <root level="WARN">
+ <appender-ref ref="STDOUT"/>
+ </root>
+</configuration>
\ No newline at end of file
diff --git a/integration-tests/it-common/src/main/resources/microservice.yaml b/integration-tests/it-common/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..d4a11c7
--- /dev/null
+++ b/integration-tests/it-common/src/main/resources/microservice.yaml
@@ -0,0 +1,46 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+servicecomb-config-order: -10000
+
+APPLICATION_ID: integration-test
+service_description:
+ name: $invalid-name-must-be-overridden
+ version: 1.0.0
+servicecomb:
+ service:
+ registry:
+ address: http://127.0.0.1:30100
+ request:
+ # 10 minute
+ timeout: 600000
+ rest:
+ address: 0.0.0.0:0
+ server:
+ thread-count: 8
+ client:
+ thread-count: 8
+ connection:
+ maxPoolSize: 30
+ highway:
+ address: 0.0.0.0:0
+ server:
+ thread-count: 8
+ client:
+ thread-count: 8
+ uploads:
+ directory: target
\ No newline at end of file
diff --git a/integration-tests/it-consumer/pom.xml b/integration-tests/it-consumer/pom.xml
new file mode 100644
index 0000000..9821cab
--- /dev/null
+++ b/integration-tests/it-consumer/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>integration-tests</artifactId>
+ <groupId>org.apache.servicecomb.tests</groupId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>it-consumer</artifactId>
+ <name>Java Chassis::IT::Consumer</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.servicecomb.tests</groupId>
+ <artifactId>it-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-model</artifactId>
+ <version>3.3.9</version>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <it.main>org.apache.servicecomb.it.ConsumerMain</it.main>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
new file mode 100644
index 0000000..ded64d1
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
@@ -0,0 +1,135 @@
+/*
+ * 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.it;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.servicecomb.core.Const;
+import org.apache.servicecomb.core.SCBEngine;
+import org.apache.servicecomb.foundation.common.utils.BeanUtils;
+import org.apache.servicecomb.it.deploy.Deploys;
+import org.apache.servicecomb.it.junit.ITJUnitUtils;
+import org.apache.servicecomb.it.testcase.base.TestDataTypePojo;
+import org.apache.servicecomb.it.testcase.base.TestDataTypeRest;
+import org.apache.servicecomb.it.testcase.support.ProducerDevMode;
+import org.apache.servicecomb.transport.highway.HighwayTransport;
+
+
+public class ConsumerMain {
+ private static ResultPrinter resultPrinter = new ResultPrinter();
+
+ private static Deploys deploys = new Deploys();
+
+ private static List<String> transports;
+
+ public static boolean autoExit = true;
+
+ public static void main(String[] args) throws Throwable {
+ BeanUtils.init();
+ ITUtils.waitBootFinished();
+
+ deploys.init();
+ run();
+
+ SCBEngine.getInstance().destroy();
+ resultPrinter.print();
+
+ if (autoExit) {
+ System.exit(0);
+ }
+ }
+
+ protected static void run() throws Throwable {
+ // deploy edge/zuul
+ // if not ready, will start a new instance and wait for ready
+ deploys.getEdge().ensureReady();
+ // deploys.getZuul().ensureReady(zuul);
+
+ // 1.base test case
+ // include all extension point abnormal scenes test case
+
+ // deploy standalone base-producer
+ // only run one case for "any" transport
+ // run highway
+ // run rest
+ // run native restTemplate to edge/zuul
+ // stop standalone base-producer
+ transports = Arrays.asList(HighwayTransport.NAME, Const.RESTFUL);
+ testStandalone();
+
+ transports = Arrays.asList(Const.RESTFUL);
+ // deploy tomcat base-producer
+ // run vertx-servlet
+ // run native restTemplate to edge/zuul
+ // stop tomcat base-producer
+
+ // deploy spring boot base-producer
+ // run vertx-servlet
+ // run native restTemplate to edge/zuul
+ // stop spring boot base-producer
+
+ // 2.complex test case
+ // 1)start new producer version
+ // consumer/edge/zuul should ......
+ // 2)delete new producer version
+ // consumer/edge/zuul should ......
+ // ......
+
+ // 3.deploy development mode producer
+ // ......
+
+ deploys.getEdge().stop();
+ }
+
+ private static void testStandalone() throws Throwable {
+ deploys.getBaseProducer().ensureReady();
+ ITJUnitUtils.addParent("standalone");
+
+ testDataType();
+
+ ITJUnitUtils.getParents().pop();
+ deploys.getBaseProducer().stop();
+ }
+
+ private static void testDataType() {
+ testDataType(ProducerDevMode.Pojo, TestDataTypePojo.class);
+ testDataType(ProducerDevMode.Jaxrs, TestDataTypeRest.class);
+ testDataType(ProducerDevMode.Springmvc, TestDataTypeRest.class);
+
+ ITJUnitUtils.getParents().push("edge");
+// runEdge();
+ ITJUnitUtils.getParents().pop();
+
+ ITJUnitUtils.getParents().push("zuul");
+// runEdge();
+ ITJUnitUtils.getParents().pop();
+ }
+
+ private static void testDataType(ProducerDevMode producerDevMode, Class<?>... classes) {
+ ITJUnitUtils.addParent(producerDevMode.name());
+ for (String transport : transports) {
+ ITJUnitUtils.addParent(transport);
+
+ ITUtils.invokeExactStaticMethod(classes, "init", transport, producerDevMode);
+ ITJUnitUtils.run(classes);
+
+ ITJUnitUtils.getParents().pop();
+ }
+ ITJUnitUtils.getParents().pop();
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ResultPrinter.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ResultPrinter.java
new file mode 100644
index 0000000..2a35762
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ResultPrinter.java
@@ -0,0 +1,65 @@
+/*
+ * 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.it;
+
+import org.apache.servicecomb.it.junit.ITJUnitUtils;
+import org.apache.servicecomb.it.junit.SCBFailure;
+
+public class ResultPrinter {
+ private long start = System.currentTimeMillis();
+
+ public String formatTotalTime() {
+ long totalTime = System.currentTimeMillis() - start;
+ long hour = 0;
+ long minute = 0;
+ long second = 0;
+ second = totalTime / 1000;
+ if (totalTime <= 1000 && totalTime > 0) {
+ second = 1;
+ }
+ if (second > 60) {
+ minute = second / 60;
+ second = second % 60;
+ }
+ if (minute > 60) {
+ hour = minute / 60;
+ minute = minute % 60;
+ }
+ // 转换时分秒 00:00:00
+ String duration =
+ (hour >= 10 ? hour : "0" + hour) + ":" + (minute >= 10 ? minute : "0" + minute) + ":" + (second >= 10 ? second
+ : "0" + second);
+ return duration;
+ }
+
+ public void print() {
+ StringBuilder sb = new StringBuilder();
+ String totalTime = formatTotalTime();
+ for (SCBFailure failure : ITJUnitUtils.getFailures()) {
+ sb.append(String.format("%s, %s\n"
+ + "%s\n",
+ failure.getParents(),
+ failure.getTestHeader(),
+ failure.getTrace()));
+ }
+ sb.append(String.format("\nrun count:%d, failed count: %d, totalTime: %s.\n",
+ ITJUnitUtils.getRunCount(),
+ ITJUnitUtils.getFailures().size(),
+ totalTime));
+ System.out.println(sb.toString());
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/DeployDefinition.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/DeployDefinition.java
new file mode 100644
index 0000000..dfdc158
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/DeployDefinition.java
@@ -0,0 +1,86 @@
+/*
+ * 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.it.deploy;
+
+import io.vertx.core.json.Json;
+
+public class DeployDefinition {
+ protected String deployName;
+
+ protected String displayName;
+
+ /**
+ * <pre>
+ * edge as the example:
+ * support:
+ * 1.absolute path: /home/xxx/it-edge/it-edge-1.0.0.jar
+ * 2.relate to work dir:
+ * if work dir is /home/xxx
+ * cmd is it-edge/it-edge-1.0.0.jar
+ * 3.run in ide, cmd is it-edge/it-edge-1.0.0.jar
+ * will try: integration-tests/target/it-edge/it-edge-1.0.0.jar
+ * 4.run in ide, cmd is it-edge
+ * will try: integration-tests/target/it-edge/it-edge-1.0.0.jar
+ * </pre>
+ */
+ protected String cmd;
+
+ protected String[] args;
+
+ public String getDeployName() {
+ return deployName;
+ }
+
+ public void setDeployName(String deployName) {
+ this.deployName = deployName;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
+ public String getCmd() {
+ return cmd;
+ }
+
+ public void setCmd(String cmd) {
+ this.cmd = cmd;
+ }
+
+ public String[] getArgs() {
+ return args;
+ }
+
+ public void setArgs(String[] args) {
+ this.args = args;
+ }
+
+ public void init() {
+ if (displayName == null) {
+ displayName = deployName;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return Json.encodePrettily(this);
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/Deploys.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/Deploys.java
new file mode 100644
index 0000000..aae0dad
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/Deploys.java
@@ -0,0 +1,192 @@
+/*
+ * 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.it.deploy;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Deploys {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Deploys.class);
+
+ private static final String DEFAULT_MICROSERVICE_VERSION = "1.0.0";
+
+ private String pomVersion;
+
+ public MicroserviceDeploy edge;
+
+ public MicroserviceDeploy baseProducer;
+
+ public MicroserviceDeploy zuul;
+
+ public MicroserviceDeploy getEdge() {
+ return edge;
+ }
+
+ public MicroserviceDeploy getZuul() {
+ return zuul;
+ }
+
+ public MicroserviceDeploy getBaseProducer() {
+ return baseProducer;
+ }
+
+ public void init() throws Throwable {
+ initPomVersion();
+ LOGGER.info("test version: {}", pomVersion);
+
+ initEdge();
+ initBaseProducer();
+// initZuul();
+ }
+
+ public void setPomVersion(String pomVersion) {
+ this.pomVersion = pomVersion;
+ }
+
+ private void initPomVersion() throws Throwable {
+ // already set manually
+ if (pomVersion != null) {
+ return;
+ }
+
+ // already package to jar
+ pomVersion = Deploys.class.getPackage().getImplementationVersion();
+ if (pomVersion != null) {
+ return;
+ }
+
+ // run in ide
+ MavenXpp3Reader reader = new MavenXpp3Reader();
+ Model model = reader.read(new FileReader("pom.xml"));
+ pomVersion = model.getVersion();
+ if (pomVersion != null) {
+ return;
+ }
+
+ if (model.getParent() == null) {
+ throw new IllegalStateException("can not find pom ServiceComb version");
+ }
+
+ pomVersion = model.getParent().getVersion();
+ if (pomVersion != null) {
+ return;
+ }
+
+ throw new IllegalStateException("can not find pom ServiceComb version");
+ }
+
+ private void initDeployDefinition(DeployDefinition deployDefinition) {
+ deployDefinition.init();
+ doInitDeployDefinition(deployDefinition);
+ LOGGER.info("definition of {} is: {}", deployDefinition.getDeployName(), deployDefinition);
+ }
+
+ private void doInitDeployDefinition(DeployDefinition deployDefinition) {
+ // absolute path or relate to current work dir
+ File cmd = new File(deployDefinition.getCmd());
+ if (cmd.exists() && cmd.isFile()) {
+ deployDefinition.setCmd(cmd.getAbsolutePath());
+ return;
+ }
+
+ // run in ide
+ File workDir = new File("integration-tests");
+ if (initDeployDefinition(deployDefinition, workDir)) {
+ return;
+ }
+
+ // run "mvn install"
+ workDir = new File("..").getAbsoluteFile();
+ if (initDeployDefinition(deployDefinition, workDir)) {
+ return;
+ }
+
+ throw new IllegalStateException(String
+ .format("can not find deploy cmd, work dir: %s, definition: %s", new File("").getAbsolutePath(),
+ deployDefinition));
+ }
+
+ private boolean initDeployDefinition(DeployDefinition deployDefinition, File workDir) {
+ // deployDefinition.getCmd() is it-edge/target/it-edge-1.0.0.jar
+ File cmd = new File(workDir, deployDefinition.getCmd());
+ if (cmd.exists() && cmd.isFile()) {
+ deployDefinition.setCmd(cmd.getAbsolutePath());
+ return true;
+ }
+
+ // deployDefinition.getCmd() is it-edge
+ // change it-edge to it-edge/it-edge-1.0.0.jar
+ cmd = new File(workDir, String.format("%s/target/%s-%s.jar",
+ deployDefinition.getCmd(),
+ deployDefinition.getCmd(),
+ pomVersion));
+ if (cmd.exists()) {
+ try {
+ deployDefinition.setCmd(cmd.getCanonicalPath());
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to getCanonicalPath of " + cmd.getAbsolutePath(), e);
+ }
+ return true;
+ }
+
+ return false;
+ }
+
+ private void initBaseProducer() {
+ MicroserviceDeployDefinition baseProducerDefinition = new MicroserviceDeployDefinition();
+ baseProducerDefinition.setDeployName("baseProducer");
+ baseProducerDefinition.setCmd("it-producer");
+ baseProducerDefinition.setArgs(new String[] {});
+ baseProducerDefinition.setAppId("integration-test");
+ baseProducerDefinition.setMicroserviceName("it-producer");
+ baseProducerDefinition.setVersion(DEFAULT_MICROSERVICE_VERSION);
+
+ initDeployDefinition(baseProducerDefinition);
+
+ baseProducer = new MicroserviceDeploy(baseProducerDefinition);
+ }
+
+ private void initEdge() {
+ MicroserviceDeployDefinition edgeDefinition = new MicroserviceDeployDefinition();
+ edgeDefinition.setDeployName("edge");
+ edgeDefinition.setCmd("it-edge");
+ edgeDefinition.setArgs(new String[] {});
+ edgeDefinition.setAppId("integration-test");
+ edgeDefinition.setMicroserviceName("it-edge");
+ edgeDefinition.setVersion(DEFAULT_MICROSERVICE_VERSION);
+
+ initDeployDefinition(edgeDefinition);
+
+ edge = new MicroserviceDeploy(edgeDefinition);
+ }
+
+ // private void initZuul() {
+ // MicroserviceDeployDefinition zuulDefinition = new MicroserviceDeployDefinition();
+ // zuulDefinition.setDeployName("zuul");
+ // zuulDefinition.setCmd("it-zuul");
+ //
+ // initDeployDefinition(zuulDefinition);
+ //
+ // zuul = new MicroserviceDeploy(zuulDefinition);
+ // }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeploy.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeploy.java
new file mode 100644
index 0000000..0276882
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeploy.java
@@ -0,0 +1,71 @@
+/*
+ * 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.it.deploy;
+
+import org.apache.servicecomb.it.ITUtils;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.apache.servicecomb.serviceregistry.consumer.MicroserviceVersionRule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MicroserviceDeploy extends NormalDeploy {
+ private static final Logger LOGGER = LoggerFactory.getLogger(MicroserviceDeploy.class);
+
+ private MicroserviceDeployDefinition microserviceDeployDefinition;
+
+ public MicroserviceDeploy(DeployDefinition deployDefinition) {
+ super(deployDefinition);
+ this.microserviceDeployDefinition = (MicroserviceDeployDefinition) deployDefinition;
+ }
+
+ @Override
+ public void deploy() throws Throwable {
+ super.deploy();
+ }
+
+ @Override
+ protected String[] createCmds() {
+ return new String[] {"java", "-jar", deployDefinition.getCmd()};
+ }
+
+ public void ensureReady() throws Throwable {
+ MicroserviceVersionRule microserviceVersionRule = RegistryUtils.getServiceRegistry().getAppManager()
+ .getOrCreateMicroserviceVersionRule(microserviceDeployDefinition.getAppId(),
+ microserviceDeployDefinition.getMicroserviceName(),
+ microserviceDeployDefinition.getVersion());
+ if (microserviceVersionRule.getInstances().size() > 0) {
+ LOGGER.info("{} already ready.", microserviceDeployDefinition.getDisplayName());
+ return;
+ }
+
+ deploy();
+ ITUtils.waitMicroserviceReady(microserviceDeployDefinition.getAppId(),
+ microserviceDeployDefinition.getMicroserviceName(),
+ microserviceDeployDefinition.getVersion(),
+ 1);
+ }
+
+ @Override
+ public void stop() {
+ if (subProcess == null) {
+ return;
+ }
+
+ sendCommand("ms-stop");
+ waitStop();
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeployDefinition.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeployDefinition.java
new file mode 100644
index 0000000..42d8d9e
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/MicroserviceDeployDefinition.java
@@ -0,0 +1,56 @@
+/*
+ * 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.it.deploy;
+
+public class MicroserviceDeployDefinition extends DeployDefinition {
+ private String appId;
+
+ private String microserviceName;
+
+ private String version;
+
+ public String getAppId() {
+ return appId;
+ }
+
+ public void setAppId(String appId) {
+ this.appId = appId;
+ }
+
+ public String getMicroserviceName() {
+ return microserviceName;
+ }
+
+ public void setMicroserviceName(String microserviceName) {
+ this.microserviceName = microserviceName;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ @Override
+ public void init() {
+ if (displayName == null) {
+ displayName = microserviceName + "-" + version;
+ }
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/NormalDeploy.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/NormalDeploy.java
new file mode 100644
index 0000000..f750f1e
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/NormalDeploy.java
@@ -0,0 +1,114 @@
+/*
+ * 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.it.deploy;
+
+
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.servicecomb.foundation.common.utils.JsonUtils;
+import org.apache.servicecomb.serviceregistry.RegistryUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NormalDeploy {
+ private static final Logger LOGGER = LoggerFactory.getLogger(NormalDeploy.class);
+
+ protected DeployDefinition deployDefinition;
+
+ protected Process subProcess;
+
+ protected BufferedWriter subProcessCommandWriter;
+
+ protected SubProcessLogger subProcessLogger;
+
+ public NormalDeploy(DeployDefinition deployDefinition) {
+ this.deployDefinition = deployDefinition;
+ }
+
+ public void deploy() throws Throwable {
+ String[] cmds = createCmds();
+ cmds = ArrayUtils.addAll(cmds, deployDefinition.getArgs());
+ cmds = ArrayUtils.addAll(cmds,
+ "-DselfController=" + RegistryUtils.getMicroserviceInstance().getInstanceId());
+
+ subProcess = createProcessBuilder(cmds).start();
+ subProcessCommandWriter = new BufferedWriter(new OutputStreamWriter(subProcess.getOutputStream()));
+ subProcessLogger = new SubProcessLogger(deployDefinition.getDisplayName(), subProcess.getInputStream());
+ }
+
+ protected String[] createCmds() {
+ return new String[] {deployDefinition.getCmd()};
+ }
+
+ protected ProcessBuilder createProcessBuilder(String[] cmds) {
+ return new ProcessBuilder(cmds).redirectErrorStream(true);
+ }
+
+ public void sendCommand(Object command) {
+ String strCmd = null;
+ try {
+ strCmd = JsonUtils.writeValueAsString(command);
+ subProcessCommandWriter.write(strCmd + "\n");
+ subProcessCommandWriter.flush();
+ } catch (Throwable e) {
+ LOGGER.error("Failed to send command, displayName={}, command={}", deployDefinition.getDisplayName(), strCmd, e);
+ }
+ }
+
+ protected void afterStop() {
+ IOUtils.closeQuietly(subProcessCommandWriter);
+ subProcessCommandWriter = null;
+
+ IOUtils.closeQuietly(subProcessLogger);
+ subProcessLogger = null;
+ }
+
+ public void waitStop() {
+ if (subProcess == null) {
+ LOGGER.info("Ignore, already stop, displayName={}.", deployDefinition.getDisplayName());
+ return;
+ }
+
+ for (; ; ) {
+ try {
+ subProcess.waitFor();
+ break;
+ } catch (InterruptedException e) {
+ LOGGER.info("Ignore InterruptedException, try to wait stop again, displayName={}.",
+ deployDefinition.getDisplayName());
+ }
+ }
+ subProcess = null;
+ afterStop();
+
+ LOGGER.info("finished stop {}.", deployDefinition.getDisplayName());
+ }
+
+ public void stop() {
+ if (subProcess == null) {
+ LOGGER.info("Ignore, already stop, displayName={}.", deployDefinition.getDisplayName());
+ return;
+ }
+
+ subProcess.destroy();
+ subProcess = null;
+ afterStop();
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/SubProcessLogger.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/SubProcessLogger.java
new file mode 100644
index 0000000..0189eef
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/deploy/SubProcessLogger.java
@@ -0,0 +1,68 @@
+/*
+ * 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.it.deploy;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SubProcessLogger implements Closeable {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SubProcessLogger.class);
+
+ private final String displayName;
+
+ private BufferedReader reader;
+
+ private Thread thread;
+
+ public SubProcessLogger(String displayName, InputStream inputStream) {
+ this.displayName = displayName;
+
+ BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
+ this.reader = new BufferedReader(new InputStreamReader(bufferedInputStream));
+
+ thread = new Thread(this::run, "SubProcessLogger-" + displayName);
+ thread.start();
+ }
+
+ private void run() {
+ try {
+ doRun();
+ } catch (IOException e) {
+ LOGGER.error("Failed to read log.", e);
+ }
+ }
+
+ private void doRun() throws IOException {
+ String line;
+ while ((line = reader.readLine()) != null) {
+ System.out.print(String.format("[%s] ", displayName));
+ System.out.println(line);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ reader.close();
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequest.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequest.java
new file mode 100644
index 0000000..567e487
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.it.extend.engine;
+
+import java.net.URI;
+
+import org.apache.servicecomb.core.CseContext;
+import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
+import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpRequest;
+import org.springframework.http.HttpMethod;
+
+public class ITClientHttpRequest extends CseClientHttpRequest {
+ private String transport;
+
+ public ITClientHttpRequest(URI uri, HttpMethod method, String transport) {
+ super(uri, method);
+ this.transport = transport;
+ }
+
+ @Override
+ protected ReferenceConfig findReferenceConfig(String microserviceName) {
+ ReferenceConfig referenceConfig = CseContext.getInstance().getConsumerProviderManager()
+ .createReferenceConfig(microserviceName);
+ if (transport != null) {
+ referenceConfig.setTransport(transport);
+ }
+ return referenceConfig;
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequestFactory.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequestFactory.java
new file mode 100644
index 0000000..5ec5ba6
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITClientHttpRequestFactory.java
@@ -0,0 +1,36 @@
+/*
+ * 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.it.extend.engine;
+
+import java.net.URI;
+
+import org.apache.servicecomb.provider.springmvc.reference.CseClientHttpRequestFactory;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.client.ClientHttpRequest;
+
+public class ITClientHttpRequestFactory extends CseClientHttpRequestFactory {
+ private String transport;
+
+ public void setTransport(String transport) {
+ this.transport = transport;
+ }
+
+ @Override
+ public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) {
+ return new ITClientHttpRequest(uri, httpMethod, transport);
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITInvoker.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITInvoker.java
new file mode 100644
index 0000000..eea40b9
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/extend/engine/ITInvoker.java
@@ -0,0 +1,69 @@
+/*
+ * 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.it.extend.engine;
+
+import java.lang.reflect.Proxy;
+
+import org.apache.servicecomb.core.CseContext;
+import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
+import org.apache.servicecomb.provider.pojo.Invoker;
+
+/**
+ * allow set transport, that makes integration test easier
+ */
+public class ITInvoker extends Invoker {
+ public static <T> T createProxy(String microserviceName, String schemaId, String transport, Class<?> consumerIntf) {
+ ITInvoker invoker = new ITInvoker(microserviceName, schemaId, transport, consumerIntf);
+ return invoker.getProxy();
+ }
+
+ private String transport;
+
+ private Object proxy;
+
+ public ITInvoker(String microserviceName, String schemaId, String transport, Class<?> consumerIntf) {
+ super(microserviceName, schemaId, consumerIntf);
+ this.transport = transport;
+ this.proxy = Proxy.newProxyInstance(consumerIntf.getClassLoader(), new Class<?>[] {consumerIntf}, this);
+ }
+
+ public String getMicroserviceName() {
+ return microserviceName;
+ }
+
+ public String getSchemaId() {
+ return schemaId;
+ }
+
+ public String getTransport() {
+ return transport;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T getProxy() {
+ return (T) proxy;
+ }
+
+ @Override
+ protected ReferenceConfig findReferenceConfig() {
+ ReferenceConfig referenceConfig = CseContext.getInstance()
+ .getConsumerProviderManager()
+ .createReferenceConfig(microserviceName);
+ referenceConfig.setTransport(transport);
+ return referenceConfig;
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/ITJUnitUtils.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/ITJUnitUtils.java
new file mode 100644
index 0000000..fc9a2b2
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/ITJUnitUtils.java
@@ -0,0 +1,102 @@
+/*
+ * 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.it.junit;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.servicecomb.foundation.common.utils.JvmUtils;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+
+import com.google.common.reflect.ClassPath;
+
+public final class ITJUnitUtils {
+ private static ClassLoader classLoader = JvmUtils.findClassLoader();
+
+ private static JUnitCore jUnitCore = new JUnitCore();
+
+ private static Stack<String> parents = new Stack<>();
+
+ private static List<SCBFailure> failures = new ArrayList<>();
+
+ private static AtomicInteger runCount = new AtomicInteger();
+
+ static {
+ jUnitCore.addListener(new RunListener() {
+ @Override
+ public void testFailure(Failure failure) {
+ SCBFailure scbFailure = new SCBFailure(failure.getDescription(), failure.getException());
+ failures.add(scbFailure);
+ System.out.println(scbFailure.toString());
+ }
+ });
+ }
+
+ private ITJUnitUtils() {
+ }
+
+ public static int getRunCount() {
+ return runCount.get();
+ }
+
+ public static Stack<String> getParents() {
+ return parents;
+ }
+
+ public static void addParent(String name) {
+ parents.add(name);
+ }
+
+ public static void popParent() {
+ parents.pop();
+ }
+
+ public static List<String> cloneParents() {
+ return new ArrayList<>(parents);
+ }
+
+ public static List<SCBFailure> getFailures() {
+ return failures;
+ }
+
+ public static void runFromPackage(String packageName) {
+ Class<?>[] classes = findAllClassInPackage(packageName);
+ run(classes);
+ }
+
+ public static void run(Class<?>... classes) {
+ Result result = jUnitCore.run(classes);
+ runCount.addAndGet(result.getRunCount());
+ }
+
+ public static Class<?>[] findAllClassInPackage(String packageName) {
+ try {
+ return ClassPath.from(classLoader)
+ .getTopLevelClassesRecursive(packageName).stream()
+ .map(clsInfo -> clsInfo.load())
+ .toArray(Class[]::new);
+ } catch (IOException e) {
+ throw new IllegalStateException("failed to find all classes in package " + packageName, e);
+ }
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/SCBFailure.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/SCBFailure.java
new file mode 100644
index 0000000..faa3c23
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/junit/SCBFailure.java
@@ -0,0 +1,37 @@
+/*
+ * 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.it.junit;
+
+import java.util.List;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+
+public class SCBFailure extends Failure {
+ private static final long serialVersionUID = 6467681668616080232L;
+
+ private List<String> parents;
+
+ public SCBFailure(Description description, Throwable thrownException) {
+ super(description, thrownException);
+ parents = ITJUnitUtils.cloneParents();
+ }
+
+ public List<String> getParents() {
+ return parents;
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypePojo.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypePojo.java
new file mode 100644
index 0000000..a7d660e
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypePojo.java
@@ -0,0 +1,66 @@
+/*
+ * 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.it.testcase.base;
+
+import org.apache.servicecomb.it.extend.engine.ITClientHttpRequestFactory;
+import org.apache.servicecomb.it.extend.engine.ITInvoker;
+import org.apache.servicecomb.it.testcase.support.DataTypePojoIntf;
+import org.apache.servicecomb.it.testcase.support.ProducerDevMode;
+import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.web.client.RestTemplate;
+
+public class TestDataTypePojo {
+ private static DataTypePojoIntf dataTypePojoIntf;
+
+ private static ITClientHttpRequestFactory clientHttpRequestFactory = new ITClientHttpRequestFactory();
+
+ private static RestTemplate restTemplate = new CseRestTemplate();
+
+ private static String urlPrefix;
+
+ private static String transport;
+
+ static {
+ restTemplate.setRequestFactory(clientHttpRequestFactory);
+ }
+
+ public static void init(String transport, ProducerDevMode producerDevMode) {
+ TestDataTypePojo.transport = transport;
+ dataTypePojoIntf = ITInvoker.createProxy("it-producer", "dataTypePojo", transport, DataTypePojoIntf.class);
+
+ clientHttpRequestFactory.setTransport(transport);
+
+ urlPrefix = "cse://it-producer/v1/dataType" + producerDevMode.name();
+ }
+
+ @Test
+ public void checkTransport_intf() {
+ Assert.assertEquals(transport, dataTypePojoIntf.checkTransport());
+ }
+
+ @Test
+ public void checkTransport_rt() {
+ Assert.assertEquals(transport, restTemplate.postForObject(urlPrefix + "/checkTransport", "", String.class));
+ }
+
+ @Test
+ public void intBody_intf() {
+ Assert.assertEquals(10, dataTypePojoIntf.intBody(10));
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypeRest.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypeRest.java
new file mode 100644
index 0000000..72d8c5d
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDataTypeRest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.it.testcase.base;
+
+import org.apache.servicecomb.it.extend.engine.ITClientHttpRequestFactory;
+import org.apache.servicecomb.it.extend.engine.ITInvoker;
+import org.apache.servicecomb.it.testcase.support.DataTypeRestIntf;
+import org.apache.servicecomb.it.testcase.support.ProducerDevMode;
+import org.apache.servicecomb.provider.springmvc.reference.CseRestTemplate;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.web.client.RestTemplate;
+
+public class TestDataTypeRest {
+ private static DataTypeRestIntf dataTypeIntf;
+
+ private static ITClientHttpRequestFactory clientHttpRequestFactory = new ITClientHttpRequestFactory();
+
+ private static RestTemplate restTemplate = new CseRestTemplate();
+
+ private static String urlPrefix;
+
+ private static String transport;
+
+ static {
+ restTemplate.setRequestFactory(clientHttpRequestFactory);
+ }
+
+ public static void init(String transport, ProducerDevMode producerDevMode) {
+ TestDataTypeRest.transport = transport;
+ dataTypeIntf = ITInvoker
+ .createProxy("it-producer", "dataType" + producerDevMode.name(), transport, DataTypeRestIntf.class);
+
+ clientHttpRequestFactory.setTransport(transport);
+
+ urlPrefix = "cse://it-producer/v1/dataType" + producerDevMode.name();
+ }
+
+ @Test
+ public void checkTransport_intf() {
+ Assert.assertEquals(transport, dataTypeIntf.checkTransport());
+ }
+
+ @Test
+ public void checkTransport_rt() {
+ Assert.assertEquals(transport, restTemplate.getForObject(urlPrefix + "/checkTransport", String.class));
+ }
+
+ @Test
+ public void intPath_intf() {
+ int expect = 10;
+ Assert.assertEquals(expect, dataTypeIntf.intPath(expect));
+ }
+
+ @Test
+ public void intPath_rt() {
+ int expect = 10;
+ Assert.assertEquals(expect, (int) restTemplate.getForObject(urlPrefix + "/intPath/" + expect, int.class));
+ }
+
+ @Test
+ public void intQuery() {
+ Assert.assertEquals(10, dataTypeIntf.intQuery(10));
+ }
+
+ @Test
+ public void intHeader() {
+ Assert.assertEquals(10, dataTypeIntf.intHeader(10));
+ }
+
+ @Test
+ public void intCookie() {
+ Assert.assertEquals(10, dataTypeIntf.intCookie(10));
+ }
+
+ @Test
+ public void intBody() {
+ Assert.assertEquals(10, dataTypeIntf.intBody(10));
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDownload.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDownload.java
new file mode 100644
index 0000000..b84c0a4
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestDownload.java
@@ -0,0 +1,142 @@
+/*
+ * 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.it.testcase.base;
+
+import org.apache.servicecomb.it.testcase.support.DownloadSchemaIntf;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestDownload {
+ private static DownloadSchemaIntf intf = Invoker
+ .createProxy("it-producer", "download", DownloadSchemaIntf.class);
+
+ static int x;
+
+ @Test
+ public void test1() {
+ x++;
+ System.out.println("test" + x);
+// intf.tempFileEntity("abc");
+ }
+
+ @Test
+ public void test2() {
+ x++;
+ System.out.println("test2");
+ Assert.assertEquals(x, x + 1);
+ }
+// private File dir = new File("target/download");
+//
+//
+// private RestTemplate restTemplate = new CseRestTemplate();
+//
+// private String prefix = "cse://springmvc/download";
+//
+// private List<CompletableFuture<?>> futures = new ArrayList<>();
+//
+// private String content = "file content";
+//
+// public TestDownload() {
+// FileUtils.deleteQuietly(dir);
+// }
+//
+// private String readFileToString(File file) {
+// try {
+// return FileUtils.readFileToString(file);
+// } catch (IOException e) {
+// return "read file failed:" + e.getMessage();
+// }
+// }
+//
+// private CompletableFuture<File> checkFile(ReadStreamPart part) {
+// CompletableFuture<File> future = part.saveToFile("target/download/"
+// + UUID.randomUUID().toString()
+// + "-"
+// + part.getSubmittedFileName());
+// return checkFuture(future);
+// }
+//
+// private <T> CompletableFuture<T> checkFuture(CompletableFuture<T> future) {
+// Error error = new Error();
+// future.whenComplete((result, e) -> {
+// Object value = result;
+// if (File.class.isInstance(value)) {
+// File file = (File) value;
+// value = readFileToString(file);
+// file.delete();
+// } else if (byte[].class.isInstance(value)) {
+// value = new String((byte[]) value);
+// }
+//
+// TestMgr.check(content, value, error);
+// });
+//
+// return future;
+// }
+//
+// private ReadStreamPart templateGet(String methodPath) {
+// return restTemplate
+// .getForObject(prefix + "/" + methodPath + "?content={content}",
+// ReadStreamPart.class,
+// content);
+// }
+//
+// public void runRest() {
+// futures.add(checkFile(intf.tempFileEntity(content)));
+// futures.add(checkFuture(templateGet("tempFileEntity").saveAsBytes()));
+//
+// futures.add(checkFile(intf.tempFilePart(content)));
+// futures.add(checkFuture(templateGet("tempFilePart").saveAsString()));
+//
+// futures.add(checkFile(intf.file(content)));
+// futures.add(checkFuture(templateGet("file").saveAsString()));
+//
+// {
+// ReadStreamPart part = intf.chineseAndSpaceFile(content);
+// TestMgr.check("测 试.test.txt", part.getSubmittedFileName());
+// futures.add(checkFile(part));
+//
+// part = templateGet("chineseAndSpaceFile");
+// TestMgr.check("测 试.test.txt", part.getSubmittedFileName());
+// futures.add(checkFuture(part.saveAsString()));
+// }
+//
+// futures.add(checkFile(intf.resource(content)));
+// futures.add(checkFuture(templateGet("resource").saveAsString()));
+//
+// futures.add(checkFile(intf.entityResource(content)));
+// futures.add(checkFuture(templateGet("entityResource").saveAsString()));
+//
+// futures.add(checkFile(intf.entityInputStream(content)));
+// futures.add(checkFuture(templateGet("entityInputStream").saveAsString()));
+//
+// futures.add(checkFile(intf.bytes(content)));
+// futures.add(checkFuture(templateGet("bytes").saveAsString()));
+//
+// futures.add(checkFile(intf.netInputStream(content)));
+// futures.add(checkFuture(templateGet("netInputStream").saveAsString()));
+//
+// try {
+// CompletableFuture
+// .allOf(futures.toArray(new CompletableFuture[futures.size()]))
+// .get();
+// } catch (InterruptedException | ExecutionException e1) {
+// TestMgr.failed("test download failed.", e1);
+// }
+// }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestGeneric.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestGeneric.java
new file mode 100644
index 0000000..4c85af1
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/base/TestGeneric.java
@@ -0,0 +1,26 @@
+/*
+ * 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.it.testcase.base;
+
+import org.junit.Test;
+
+public class TestGeneric {
+ @Test
+ public void test() {
+
+ }
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypePojoIntf.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypePojoIntf.java
new file mode 100644
index 0000000..7146279
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypePojoIntf.java
@@ -0,0 +1,22 @@
+package org.apache.servicecomb.it.testcase.support;/*
+ * 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.
+ */
+
+public interface DataTypePojoIntf {
+ String checkTransport();
+
+ int intBody(int input);
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypeRestIntf.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypeRestIntf.java
new file mode 100644
index 0000000..3a794b9
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DataTypeRestIntf.java
@@ -0,0 +1,30 @@
+package org.apache.servicecomb.it.testcase.support;/*
+ * 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.
+ */
+
+public interface DataTypeRestIntf {
+ String checkTransport();
+
+ int intPath(int input);
+
+ int intQuery(int input);
+
+ int intHeader(int input);
+
+ int intCookie(int input);
+
+ int intBody(int input);
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DownloadSchemaIntf.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DownloadSchemaIntf.java
new file mode 100644
index 0000000..9bc373f
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/DownloadSchemaIntf.java
@@ -0,0 +1,39 @@
+/*
+ * 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.it.testcase.support;
+
+import org.apache.servicecomb.foundation.vertx.http.ReadStreamPart;
+
+public interface DownloadSchemaIntf {
+ ReadStreamPart tempFileEntity(String content);
+
+ ReadStreamPart tempFilePart(String content);
+
+ ReadStreamPart file(String content);
+
+ ReadStreamPart chineseAndSpaceFile(String content);
+
+ ReadStreamPart resource(String content);
+
+ ReadStreamPart entityResource(String content);
+
+ ReadStreamPart entityInputStream(String content);
+
+ ReadStreamPart bytes(String content);
+
+ ReadStreamPart netInputStream(String content);
+}
diff --git a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/ProducerDevMode.java b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/ProducerDevMode.java
new file mode 100644
index 0000000..c264293
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/support/ProducerDevMode.java
@@ -0,0 +1,22 @@
+package org.apache.servicecomb.it.testcase.support;/*
+ * 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.
+ */
+
+public enum ProducerDevMode {
+ Pojo,
+ Jaxrs,
+ Springmvc
+}
diff --git a/integration-tests/it-consumer/src/main/resources/microservice.yaml b/integration-tests/it-consumer/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..387fcb3
--- /dev/null
+++ b/integration-tests/it-consumer/src/main/resources/microservice.yaml
@@ -0,0 +1,19 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+service_description:
+ name: it-consumer
diff --git a/integration-tests/it-consumer/src/test/java/org/apache/servicecomb/it/TestMain.java b/integration-tests/it-consumer/src/test/java/org/apache/servicecomb/it/TestMain.java
new file mode 100644
index 0000000..ce4b42f
--- /dev/null
+++ b/integration-tests/it-consumer/src/test/java/org/apache/servicecomb/it/TestMain.java
@@ -0,0 +1,30 @@
+/*
+ * 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.it;
+
+import org.apache.servicecomb.it.junit.ITJUnitUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestMain {
+ @Test
+ public void testMain() throws Throwable {
+ ConsumerMain.autoExit = false;
+ ConsumerMain.main(new String[] {});
+ Assert.assertTrue(ITJUnitUtils.getFailures().isEmpty());
+ }
+}
diff --git a/integration-tests/it-edge/enable-it-jar b/integration-tests/it-edge/enable-it-jar
new file mode 100644
index 0000000..e69de29
diff --git a/integration-tests/it-edge/pom.xml b/integration-tests/it-edge/pom.xml
new file mode 100644
index 0000000..6ac4123
--- /dev/null
+++ b/integration-tests/it-edge/pom.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>integration-tests</artifactId>
+ <groupId>org.apache.servicecomb.tests</groupId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>it-edge</artifactId>
+ <name>Java Chassis::IT::Edge</name>
+
+ <properties>
+ <it.main>org.apache.servicecomb.it.edge.EdgeMain</it.main>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.servicecomb.tests</groupId>
+ <artifactId>it-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb</groupId>
+ <artifactId>edge-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb</groupId>
+ <artifactId>handler-loadbalance</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb</groupId>
+ <artifactId>provider-pojo</artifactId>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/Auth.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/Auth.java
new file mode 100644
index 0000000..6718069
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/Auth.java
@@ -0,0 +1,24 @@
+/*
+ * 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.it.authentication;
+
+import java.util.concurrent.CompletableFuture;
+
+public interface Auth {
+ CompletableFuture<Boolean> auth(String info);
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/encrypt/Hcr.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/encrypt/Hcr.java
new file mode 100644
index 0000000..c219b0e
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/authentication/encrypt/Hcr.java
@@ -0,0 +1,39 @@
+/*
+ * 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.it.authentication.encrypt;
+
+public class Hcr {
+ private String bodyKey;
+
+ private String signatureKey;
+
+ public String getBodyKey() {
+ return bodyKey;
+ }
+
+ public void setBodyKey(String bodyKey) {
+ this.bodyKey = bodyKey;
+ }
+
+ public String getSignatureKey() {
+ return signatureKey;
+ }
+
+ public void setSignatureKey(String signatureKey) {
+ this.signatureKey = signatureKey;
+ }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeConst.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeConst.java
new file mode 100644
index 0000000..a8d1b52
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeConst.java
@@ -0,0 +1,20 @@
+package org.apache.servicecomb.it.edge;/*
+ * 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.
+ */
+
+public interface EdgeConst {
+ String ENCRYPT_CONTEXT = "encryptContext";
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeDispatcher.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeDispatcher.java
new file mode 100644
index 0000000..7770c7c
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeDispatcher.java
@@ -0,0 +1,58 @@
+/*
+ * 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.it.edge;
+
+import java.util.Map;
+
+import org.apache.servicecomb.edge.core.AbstractEdgeDispatcher;
+import org.apache.servicecomb.edge.core.CompatiblePathVersionMapper;
+import org.apache.servicecomb.edge.core.EdgeInvocation;
+
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.RoutingContext;
+import io.vertx.ext.web.handler.CookieHandler;
+
+public class EdgeDispatcher extends AbstractEdgeDispatcher {
+ private CompatiblePathVersionMapper versionMapper = new CompatiblePathVersionMapper();
+
+ @Override
+ public int getOrder() {
+ return 10000;
+ }
+
+ @Override
+ public void init(Router router) {
+ String regex = "/api/([^\\\\/]+)/([^\\\\/]+)/(.*)";
+ router.routeWithRegex(regex).handler(CookieHandler.create());
+ router.routeWithRegex(regex).handler(createBodyHandler());
+ router.routeWithRegex(regex).failureHandler(this::onFailure).handler(this::onRequest);
+ }
+
+ protected void onRequest(RoutingContext context) {
+ Map<String, String> pathParams = context.pathParams();
+ String microserviceName = pathParams.get("param0");
+ String pathVersion = pathParams.get("param1");
+ String path = context.request().path().substring(5 + microserviceName.length());
+
+ EdgeInvocation edgeInvocation = new EdgeInvocation();
+ edgeInvocation.setVersionRule(versionMapper.getOrCreate(pathVersion).getVersionRule());
+
+ edgeInvocation.init(microserviceName, context, path, httpServerFilters);
+ edgeInvocation.edgeInvoke();
+ }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeMain.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeMain.java
new file mode 100644
index 0000000..3a042c6
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/EdgeMain.java
@@ -0,0 +1,26 @@
+/*
+ * 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.it.edge;
+
+import org.apache.servicecomb.it.ITMain;
+
+public class EdgeMain {
+ public static void main(String[] args) {
+ ITMain.main(args);
+ }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/Encrypt.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/Encrypt.java
new file mode 100644
index 0000000..cacc213
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/Encrypt.java
@@ -0,0 +1,28 @@
+/*
+ * 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.it.edge.encrypt;
+
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+
+public interface Encrypt {
+ CompletableFuture<String> queryUserId(String serviceToken);
+
+ CompletableFuture<Hcr> queryHcr(String hcrId);
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptContext.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptContext.java
new file mode 100644
index 0000000..0f03796
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptContext.java
@@ -0,0 +1,46 @@
+/*
+ * 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.it.edge.encrypt;
+
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+
+public class EncryptContext {
+ private Hcr hcr;
+
+ private String userId;
+
+ public EncryptContext(Hcr hcr, String userId) {
+ this.hcr = hcr;
+ this.userId = userId;
+ }
+
+ public Hcr getHcr() {
+ return hcr;
+ }
+
+ public void setHcr(Hcr hcr) {
+ this.hcr = hcr;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ public void setUserId(String userId) {
+ this.userId = userId;
+ }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeDispatcher.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeDispatcher.java
new file mode 100644
index 0000000..6c2bca7
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeDispatcher.java
@@ -0,0 +1,114 @@
+/*
+ * 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.it.edge.encrypt;
+
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.servicecomb.edge.core.AbstractEdgeDispatcher;
+import org.apache.servicecomb.edge.core.CompatiblePathVersionMapper;
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.vertx.core.http.HttpServerRequest;
+import io.vertx.ext.web.Router;
+import io.vertx.ext.web.RoutingContext;
+import io.vertx.ext.web.handler.CookieHandler;
+
+public class EncryptEdgeDispatcher extends AbstractEdgeDispatcher {
+ private static final Logger LOGGER = LoggerFactory.getLogger(EncryptEdgeDispatcher.class);
+
+ private CompatiblePathVersionMapper versionMapper = new CompatiblePathVersionMapper();
+
+ private Encrypt encrypt = Invoker.createProxy("auth", "encrypt", Encrypt.class);
+
+ private String prefix = "encryptApi";
+
+ @Override
+ public int getOrder() {
+ return 10000;
+ }
+
+ @Override
+ public void init(Router router) {
+ {
+ String regex = "/" + prefix + "/([^\\\\/]+)/([^\\\\/]+)/(.*)";
+ router.routeWithRegex(regex).handler(CookieHandler.create());
+ router.routeWithRegex(regex).handler(createBodyHandler());
+ router.routeWithRegex(regex).failureHandler(this::onFailure).handler(this::onRequest);
+ }
+ }
+
+ protected void onRequest(RoutingContext context) {
+ HttpServerRequest httpServerRequest = context.request();
+
+ // queryUserId always success
+ CompletableFuture<String> userIdFuture = queryUserId(httpServerRequest);
+ queryHcr(httpServerRequest).thenCombine(userIdFuture, (hcr, userId) -> {
+ // hcr and userId all success
+ routeToBackend(context, hcr, userId);
+ return null;
+ }).whenComplete((v, e) -> {
+ // failed to query hcr
+ if (e != null) {
+ context.response().end("failed to query hcr: " + e.getMessage());
+ return;
+ }
+ });
+ }
+
+ private CompletableFuture<String> queryUserId(HttpServerRequest httpServerRequest) {
+ String serviceToken = httpServerRequest.getParam("serviceToken");
+ if (serviceToken == null) {
+ // no need to query userId
+ return CompletableFuture.completedFuture(null);
+ }
+
+ CompletableFuture<String> future = new CompletableFuture<>();
+ encrypt.queryUserId(serviceToken).whenComplete((userId, e) -> {
+ if (e != null) {
+ // treat as success, just userId is null
+ LOGGER.error("Failed to query userId, serviceToken={}.", serviceToken, e);
+ }
+
+ future.complete(userId);
+ });
+
+ return future;
+ }
+
+ private CompletableFuture<Hcr> queryHcr(HttpServerRequest httpServerRequest) {
+ String hcrId = httpServerRequest.getParam("hcrId");
+ return encrypt.queryHcr(hcrId);
+ }
+
+ private void routeToBackend(RoutingContext context, Hcr hcr, String userId) {
+ Map<String, String> pathParams = context.pathParams();
+ String microserviceName = pathParams.get("param0");
+ String pathVersion = pathParams.get("param1");
+ String path = context.request().path().substring(prefix.length() + 1);
+
+ EncryptEdgeInvocation edgeInvocation = new EncryptEdgeInvocation(new EncryptContext(hcr, userId));
+ edgeInvocation.setVersionRule(versionMapper.getOrCreate(pathVersion).getVersionRule());
+
+ edgeInvocation.init(microserviceName, context, path, httpServerFilters);
+ edgeInvocation.edgeInvoke();
+ }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeInvocation.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeInvocation.java
new file mode 100644
index 0000000..c9d2c92
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/EncryptEdgeInvocation.java
@@ -0,0 +1,34 @@
+/*
+ * 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.it.edge.encrypt;
+
+import org.apache.servicecomb.edge.core.EdgeInvocation;
+
+public class EncryptEdgeInvocation extends EdgeInvocation {
+ private EncryptContext encryptContext;
+
+ public EncryptEdgeInvocation(EncryptContext encryptContext) {
+ this.encryptContext = encryptContext;
+ }
+
+ @Override
+ protected void createInvocation() {
+ super.createInvocation();
+
+ invocation.getHandlerContext().put("encryptContext", encryptContext);
+ }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/DecodeBodyFilter.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/DecodeBodyFilter.java
new file mode 100644
index 0000000..00f3974
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/DecodeBodyFilter.java
@@ -0,0 +1,66 @@
+/*
+ * 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.it.edge.encrypt.filter;
+
+import java.util.Map;
+
+import org.apache.servicecomb.common.rest.codec.RestObjectMapperFactory;
+import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+import org.apache.servicecomb.it.edge.EdgeConst;
+import org.apache.servicecomb.it.edge.encrypt.EncryptContext;
+import org.apache.servicecomb.swagger.invocation.Response;
+
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+
+public class DecodeBodyFilter implements HttpServerFilter {
+ private JavaType bodyType = TypeFactory.defaultInstance().constructMapType(Map.class, String.class, String[].class);
+
+ @Override
+ public int getOrder() {
+ return -9000;
+ }
+
+ @Override
+ public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+ EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT);
+ if (encryptContext == null) {
+ return null;
+ }
+ Hcr hcr = encryptContext.getHcr();
+
+ String encodedBody = requestEx.getParameter("body");
+ if (encodedBody == null) {
+ return null;
+ }
+
+ encodedBody = encodedBody.substring(hcr.getBodyKey().length());
+
+ try {
+ Map<String, String[]> decodedBody = RestObjectMapperFactory.getRestObjectMapper()
+ .readValue(encodedBody, bodyType);
+ requestEx.getParameterMap().putAll(decodedBody);
+ } catch (Throwable e) {
+ // should be a meaning exception response
+ return Response.producerFailResp(e);
+ }
+ return null;
+ }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureRequestFilter.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureRequestFilter.java
new file mode 100644
index 0000000..3eb6090
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureRequestFilter.java
@@ -0,0 +1,67 @@
+/*
+ * 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.it.edge.encrypt.filter;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+import org.apache.servicecomb.it.edge.EdgeConst;
+import org.apache.servicecomb.it.edge.encrypt.EncryptContext;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
+public class EdgeSignatureRequestFilter implements HttpServerFilter {
+ private static final Logger LOGGER = LoggerFactory.getLogger(EdgeSignatureRequestFilter.class);
+
+ @Override
+ public int getOrder() {
+ return -10000;
+ }
+
+ @Override
+ public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+ EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT);
+ if (encryptContext == null) {
+ return null;
+ }
+ Hcr hcr = encryptContext.getHcr();
+
+ // signature for query and form
+ List<String> names = Collections.list(requestEx.getParameterNames());
+ names.sort(Comparator.naturalOrder());
+
+ Hasher hasher = Hashing.sha256().newHasher();
+ hasher.putString(hcr.getSignatureKey(), StandardCharsets.UTF_8);
+ for (String name : names) {
+ hasher.putString(name, StandardCharsets.UTF_8);
+ hasher.putString(requestEx.getParameter(name), StandardCharsets.UTF_8);
+ }
+ LOGGER.info("afterReceiveRequest signature: {}", hasher.hash().toString());
+
+ return null;
+ }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureResponseFilter.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureResponseFilter.java
new file mode 100644
index 0000000..b625135
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/EdgeSignatureResponseFilter.java
@@ -0,0 +1,76 @@
+/*
+ * 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.it.edge.encrypt.filter;
+
+import java.nio.charset.StandardCharsets;
+
+import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
+import org.apache.servicecomb.it.authentication.encrypt.Hcr;
+import org.apache.servicecomb.it.edge.EdgeConst;
+import org.apache.servicecomb.it.edge.encrypt.EncryptContext;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.hash.Hasher;
+import com.google.common.hash.Hashing;
+
+import io.vertx.core.buffer.Buffer;
+
+public class EdgeSignatureResponseFilter implements HttpServerFilter {
+ private static final Logger LOGGER = LoggerFactory.getLogger(EdgeSignatureResponseFilter.class);
+
+ @Override
+ public int getOrder() {
+ return 10000;
+ }
+
+ @Override
+ public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+ return null;
+ }
+
+ @Override
+ public void beforeSendResponse(Invocation invocation, HttpServletResponseEx responseEx) {
+ if (invocation == null) {
+ return;
+ }
+
+ EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT);
+ if (encryptContext == null) {
+ return;
+ }
+ Hcr hcr = encryptContext.getHcr();
+
+ // bad practice: it's better to set signature in response header
+ Buffer bodyBuffer = responseEx.getBodyBuffer();
+ String body = bodyBuffer.toString();
+ if (body.endsWith("}")) {
+ Hasher hasher = Hashing.sha256().newHasher();
+ hasher.putString(hcr.getSignatureKey(), StandardCharsets.UTF_8);
+ hasher.putString(body, StandardCharsets.UTF_8);
+ String signature = hasher.hash().toString();
+ LOGGER.info("beforeSendResponse signature: {}", signature);
+
+ body = body.substring(0, body.length() - 1) + ",\"signature\":\"" + signature + "\"}";
+ responseEx.setBodyBuffer(Buffer.buffer(body));
+ }
+ }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/UserIdFilter.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/UserIdFilter.java
new file mode 100644
index 0000000..083dd69
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/encrypt/filter/UserIdFilter.java
@@ -0,0 +1,46 @@
+/*
+ * 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.it.edge.encrypt.filter;
+
+import org.apache.servicecomb.common.rest.filter.HttpServerFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.it.edge.EdgeConst;
+import org.apache.servicecomb.it.edge.encrypt.EncryptContext;
+import org.apache.servicecomb.swagger.invocation.Response;
+
+public class UserIdFilter implements HttpServerFilter {
+ @Override
+ public int getOrder() {
+ return -8000;
+ }
+
+ @Override
+ public Response afterReceiveRequest(Invocation invocation, HttpServletRequestEx requestEx) {
+ EncryptContext encryptContext = (EncryptContext) invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT);
+ if (encryptContext == null) {
+ return null;
+ }
+
+ String userId = encryptContext.getUserId();
+ if (userId != null) {
+ requestEx.setParameter("userId", userId);
+ }
+
+ return null;
+ }
+}
diff --git a/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/handler/AuthHandler.java b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/handler/AuthHandler.java
new file mode 100644
index 0000000..691d27c
--- /dev/null
+++ b/integration-tests/it-edge/src/main/java/org/apache/servicecomb/it/edge/handler/AuthHandler.java
@@ -0,0 +1,74 @@
+/*
+ * 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.it.edge.handler;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.servicecomb.core.Handler;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.definition.MicroserviceMeta;
+import org.apache.servicecomb.it.authentication.Auth;
+import org.apache.servicecomb.it.edge.EdgeConst;
+import org.apache.servicecomb.provider.pojo.Invoker;
+import org.apache.servicecomb.swagger.invocation.AsyncResponse;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AuthHandler implements Handler {
+ private static Logger LOGGER = LoggerFactory.getLogger(AuthHandler.class);
+
+ private static Auth auth;
+
+ static {
+ auth = Invoker.createProxy("auth", "auth", Auth.class);
+ }
+
+ @Override
+ public void init(MicroserviceMeta microserviceMeta, InvocationType invocationType) {
+ }
+
+ @Override
+ public void handle(Invocation invocation, AsyncResponse asyncResp) throws Exception {
+ if (invocation.getHandlerContext().get(EdgeConst.ENCRYPT_CONTEXT) != null) {
+ invocation.next(asyncResp);
+ return;
+ }
+
+ auth.auth("").whenComplete((succ, e) -> doHandle(invocation, asyncResp, succ, e));
+ }
+
+ protected void doHandle(Invocation invocation, AsyncResponse asyncResp, Boolean authSucc, Throwable authException) {
+ if (authException != null) {
+ asyncResp.consumerFail(new InvocationException(Status.UNAUTHORIZED, (Object) authException.getMessage()));
+ return;
+ }
+
+ if (!authSucc) {
+ asyncResp.consumerFail(new InvocationException(Status.UNAUTHORIZED, (Object) "auth failed"));
+ }
+
+ LOGGER.debug("auth success.");
+ try {
+ invocation.next(asyncResp);
+ } catch (Throwable e) {
+ asyncResp.consumerFail(e);
+ }
+ }
+}
diff --git a/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter b/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter
new file mode 100644
index 0000000..a0e033d
--- /dev/null
+++ b/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpServerFilter
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.it.edge.encrypt.filter.EdgeSignatureRequestFilter
+org.apache.servicecomb.it.edge.encrypt.filter.DecodeBodyFilter
+org.apache.servicecomb.it.edge.encrypt.filter.UserIdFilter
+org.apache.servicecomb.it.edge.encrypt.filter.EdgeSignatureResponseFilter
\ No newline at end of file
diff --git a/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher b/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
new file mode 100644
index 0000000..66f422f
--- /dev/null
+++ b/integration-tests/it-edge/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.it.edge.EdgeDispatcher
+org.apache.servicecomb.it.edge.encrypt.EncryptEdgeDispatcher
diff --git a/integration-tests/it-edge/src/main/resources/config/cse.handler.xml b/integration-tests/it-edge/src/main/resources/config/cse.handler.xml
new file mode 100644
index 0000000..c9027e7
--- /dev/null
+++ b/integration-tests/it-edge/src/main/resources/config/cse.handler.xml
@@ -0,0 +1,20 @@
+<!--
+ ~ 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.
+ -->
+
+<config>
+ <handler id="auth" class="org.apache.servicecomb.it.edge.handler.AuthHandler"/>
+</config>
diff --git a/integration-tests/it-edge/src/main/resources/microservice.yaml b/integration-tests/it-edge/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..b57a630
--- /dev/null
+++ b/integration-tests/it-edge/src/main/resources/microservice.yaml
@@ -0,0 +1,48 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+service_description:
+ name: it-edge
+
+servicecomb:
+ handler:
+ chain:
+ Consumer:
+ default: auth,loadbalance
+ service:
+ it-auth: loadbalance
+ http:
+ dispatcher:
+ edge:
+ default:
+ enabled: true
+ prefix: rest
+ withVersion: true
+ prefixSegmentCount: 1
+ url:
+ enabled: true
+ mappings:
+ businessV1:
+ prefixSegmentCount: 1
+ path: "/url/business/v1/.*"
+ microserviceName: business
+ versionRule: 1.0.0-2.0.0
+ businessV2:
+ prefixSegmentCount: 1
+ path: "/url/business/v2/.*"
+ microserviceName: business
+ versionRule: 2.0.0-3.0.0
diff --git a/integration-tests/it-producer/enable-it-jar b/integration-tests/it-producer/enable-it-jar
new file mode 100644
index 0000000..e69de29
diff --git a/integration-tests/it-producer/pom.xml b/integration-tests/it-producer/pom.xml
new file mode 100644
index 0000000..2739a43
--- /dev/null
+++ b/integration-tests/it-producer/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>integration-tests</artifactId>
+ <groupId>org.apache.servicecomb.tests</groupId>
+ <version>1.1.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>it-producer</artifactId>
+ <name>Java Chassis::IT::Producer</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.servicecomb.tests</groupId>
+ <artifactId>it-common</artifactId>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <it.main>org.apache.servicecomb.it.BaseProducerMain</it.main>
+ </properties>
+</project>
\ No newline at end of file
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/BaseProducerMain.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/BaseProducerMain.java
new file mode 100644
index 0000000..37c7191
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/BaseProducerMain.java
@@ -0,0 +1,23 @@
+/*
+ * 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.it;
+
+public class BaseProducerMain {
+ public static void main(String[] args) {
+ ITMain.main(args);
+ }
+}
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeJaxrs.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeJaxrs.java
new file mode 100644
index 0000000..b9b7b13
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeJaxrs.java
@@ -0,0 +1,74 @@
+/*
+ * 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.it.schema;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.CookieParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.QueryParam;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+
+@RestSchema(schemaId = "dataTypeJaxrs")
+@Path("/v1/dataTypeJaxrs")
+public class DataTypeJaxrs {
+ private DataTypePojo pojo = new DataTypePojo();
+
+ public void test(HttpServletRequest request, HttpServletResponse response) {
+
+ }
+
+ @Path("checkTransport")
+ @GET
+ public String checkTransport(HttpServletRequest request) {
+ return pojo.checkTransport(request);
+ }
+
+ @Path("intPath/{input}")
+ @GET
+ public int intPath(@PathParam("input") int input) {
+ return pojo.intBody(input);
+ }
+
+ @Path("intQuery")
+ @GET
+ public int intQuery(@QueryParam("input") int input) {
+ return pojo.intBody(input);
+ }
+
+ @Path("intHeader")
+ @GET
+ public int intHeader(@HeaderParam("input") int input) {
+ return pojo.intBody(input);
+ }
+
+ @Path("intCookie")
+ @GET
+ public int intCookie(@CookieParam("input") int input) {
+ return pojo.intBody(input);
+ }
+
+ @Path("intBody")
+ @GET
+ public int intBody(int input) {
+ return pojo.intBody(input);
+ }
+}
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypePojo.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypePojo.java
new file mode 100644
index 0000000..9027573
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypePojo.java
@@ -0,0 +1,42 @@
+/*
+ * 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.it.schema;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.servicecomb.core.Const;
+import org.apache.servicecomb.provider.pojo.RpcSchema;
+import org.apache.servicecomb.provider.rest.common.InvocationToHttpServletRequest;
+import org.apache.servicecomb.transport.highway.HighwayTransport;
+
+import io.swagger.annotations.SwaggerDefinition;
+
+@RpcSchema(schemaId = "dataTypePojo")
+@SwaggerDefinition(basePath = "/v1/dataTypePojo")
+public class DataTypePojo {
+ public String checkTransport(HttpServletRequest request) {
+ if (InvocationToHttpServletRequest.class.isInstance(request)) {
+ return HighwayTransport.NAME;
+ }
+
+ return Const.RESTFUL;
+ }
+
+ public int intBody(int input) {
+ return input;
+ }
+}
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeSpringmvc.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeSpringmvc.java
new file mode 100644
index 0000000..19104b7
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DataTypeSpringmvc.java
@@ -0,0 +1,64 @@
+/*
+ * 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.it.schema;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@RestSchema(schemaId = "dataTypeSpringmvc")
+@RequestMapping(path = "/v1/dataTypeSpringmvc")
+public class DataTypeSpringmvc {
+ private DataTypePojo pojo = new DataTypePojo();
+
+ @GetMapping(path = "checkTransport")
+ public String checkTransport(HttpServletRequest request) {
+ return pojo.checkTransport(request);
+ }
+
+ @GetMapping("intPath/{input}")
+ public int intPath(@PathVariable("input") int input) {
+ return pojo.intBody(input);
+ }
+
+ @GetMapping("intQuery")
+ public int intQuery(@RequestParam("input") int input) {
+ return pojo.intBody(input);
+ }
+
+ @GetMapping("intHeader")
+ public int intHeader(@RequestHeader("input") int input) {
+ return pojo.intBody(input);
+ }
+
+ @GetMapping("intCookie")
+ public int intCookie(@CookieValue("input") int input) {
+ return pojo.intBody(input);
+ }
+
+ @GetMapping("intBody")
+ public int intBody(@RequestBody int input) {
+ return pojo.intBody(input);
+ }
+}
diff --git a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
new file mode 100644
index 0000000..6ea0442
--- /dev/null
+++ b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
@@ -0,0 +1,195 @@
+/*
+ * 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.it.schema;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.UUID;
+
+import javax.servlet.http.Part;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.bootstrap.HttpServer;
+import org.apache.http.impl.bootstrap.ServerBootstrap;
+import org.apache.servicecomb.core.BootListener;
+import org.apache.servicecomb.foundation.common.part.FilePart;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.core.io.Resource;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+
+@RestSchema(schemaId = "download")
+@RequestMapping(path = "/base/v1//download")
+public class DownloadSchema implements BootListener {
+ File tempDir = new File("target/downloadTemp");
+
+ HttpServer server;
+
+ public DownloadSchema() throws IOException {
+ FileUtils.deleteQuietly(tempDir);
+ FileUtils.forceMkdir(tempDir);
+
+ // for download from net stream case
+ server = ServerBootstrap
+ .bootstrap()
+ .setListenerPort(9000)
+ .registerHandler("/download/netInputStream", (req, resp, context) -> {
+ String uri = req.getRequestLine().getUri();
+ String query = URI.create(uri).getQuery();
+ int idx = query.indexOf('=');
+ String content = query.substring(idx + 1);
+ content = URLDecoder.decode(content, StandardCharsets.UTF_8.name());
+ resp.setEntity(new StringEntity(content, StandardCharsets.UTF_8.name()));
+ }).create();
+ server.start();
+ }
+
+ @Override
+ public void onBootEvent(BootEvent event) {
+ if (EventType.AFTER_CLOSE.equals(event.getEventType())) {
+ server.stop();
+ }
+ }
+
+ protected File createTempFile(String content) throws IOException {
+ return createTempFile(null, content);
+ }
+
+ protected File createTempFile(String name, String content) throws IOException {
+ if (name == null) {
+ name = "download-" + UUID.randomUUID().toString() + ".txt";
+ }
+ File file = new File(tempDir, name);
+ FileUtils.write(file, content);
+ return file;
+ }
+
+ // customize HttpHeaders.CONTENT_DISPOSITION to be "attachment;filename=tempFileEntity.txt"
+ @GetMapping(path = "/tempFileEntity")
+ public ResponseEntity<Part> tempFileEntity(String content) throws IOException {
+ File file = createTempFile(content);
+
+ return ResponseEntity
+ .ok()
+ .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=tempFileEntity.txt")
+ .body(new FilePart(null, file)
+ .setDeleteAfterFinished(true));
+ }
+
+ // generate HttpHeaders.CONTENT_DISPOSITION to be "attachment;filename=tempFilePart.txt" automatically
+ @GetMapping(path = "/tempFilePart")
+ public Part tempFilePart(String content) throws IOException {
+ File file = createTempFile(content);
+
+ return new FilePart(null, file)
+ .setDeleteAfterFinished(true)
+ .setSubmittedFileName("tempFilePart.txt");
+ }
+
+ @GetMapping(path = "/file")
+ public File file(String content) throws IOException {
+ return createTempFile("file.txt", content);
+ }
+
+ @GetMapping(path = "/chineseAndSpaceFile")
+ public Part chineseAndSpaceFile(String content) throws IOException {
+ File file = createTempFile(content);
+ return new FilePart(null, file)
+ .setDeleteAfterFinished(true)
+ .setSubmittedFileName("测 试.test.txt");
+ }
+
+ @GetMapping(path = "/resource")
+ @ApiResponses({
+ @ApiResponse(code = 200, response = File.class, message = ""),
+ })
+ public Resource resource(String content) throws IOException {
+ return new ByteArrayResource(content.getBytes(StandardCharsets.UTF_8)) {
+ @Override
+ public String getFilename() {
+ return "resource.txt";
+ }
+ };
+ }
+
+ @GetMapping(path = "/entityResource")
+ @ApiResponses({
+ @ApiResponse(code = 200, response = File.class, message = ""),
+ })
+ public ResponseEntity<Resource> entityResource(String content) throws IOException {
+ return ResponseEntity
+ .ok()
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
+ .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=entityResource.txt")
+ .body(new ByteArrayResource(content.getBytes(StandardCharsets.UTF_8)));
+ }
+
+ @GetMapping(path = "/entityInputStream")
+ @ApiResponses({
+ @ApiResponse(code = 200, response = File.class, message = ""),
+ })
+ public ResponseEntity<InputStream> entityInputStream(String content) throws IOException {
+ return ResponseEntity
+ .ok()
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
+ .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=entityInputStream.txt")
+ .body(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)));
+ }
+
+ @GetMapping(path = "/bytes")
+ @ApiResponses({
+ @ApiResponse(code = 200, response = File.class, message = ""),
+ })
+ public ResponseEntity<byte[]> bytes(String content) throws IOException {
+ return ResponseEntity
+ .ok()
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
+ .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=bytes.txt")
+ .body(content.getBytes(StandardCharsets.UTF_8));
+ }
+
+ @GetMapping(path = "/netInputStream")
+ @ApiResponses({
+ @ApiResponse(code = 200, response = File.class, message = ""),
+ })
+ public ResponseEntity<InputStream> netInputStream(String content) throws IOException {
+ URL url = new URL("http://localhost:9000/download/netInputStream?content="
+ + URLEncoder.encode(content, StandardCharsets.UTF_8.name()));
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ return ResponseEntity
+ .ok()
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
+ .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=netInputStream.txt")
+ .body(conn.getInputStream());
+ }
+}
diff --git a/integration-tests/it-producer/src/main/resources/microservice.yaml b/integration-tests/it-producer/src/main/resources/microservice.yaml
new file mode 100644
index 0000000..102722d
--- /dev/null
+++ b/integration-tests/it-producer/src/main/resources/microservice.yaml
@@ -0,0 +1,20 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+service_description:
+ name: it-producer
+
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 078405a..9089eef 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -42,11 +42,25 @@
<module>spring-pojo-tests</module>
<module>dynamic-config-tests</module>
<module>spring-pojo-connection-limit-test</module>
+
+ <module>it-common</module>
+ <module>it-producer</module>
+ <module>it-edge</module>
+ <module>it-common-service</module>
+
+ <!--must be the last one-->
+ <module>it-consumer</module>
</modules>
<dependencyManagement>
<dependencies>
<dependency>
+ <groupId>org.apache.servicecomb.tests</groupId>
+ <artifactId>it-common</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.servicecomb.demo</groupId>
<artifactId>demo-schema</artifactId>
<version>1.1.0-SNAPSHOT</version>
@@ -123,6 +137,27 @@
<groupId>org.apache.servicecomb</groupId>
<artifactId>metrics-core</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.servicecomb</groupId>
+ <artifactId>foundation-test-scaffolding</artifactId>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
<profiles>