This is an automated email from the ASF dual-hosted git repository.

ningjiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-pack.git

commit 3002dc58172fa63809f469b4f0d5935c9e5114f3
Author: CMonkey <[email protected]>
AuthorDate: Fri Jul 5 16:55:47 2019 +0800

    add acceptance-pack-spring-demo-with-nacos module
---
 .../acceptance-pack-spring-demo-with-nacos/pom.xml | 414 +++++++++++++++++++++
 .../org/apache/servicecomb/pack/PackStepdefs.java  | 211 +++++++++++
 .../org/apache/servicecomb/pack/RunCucumberIT.java |  29 ++
 .../src/test/resources/booking_exception.btm       |  28 ++
 .../src/test/resources/booking_timeout.btm         |  36 ++
 .../src/test/resources/log4j2-test.xml             |  30 ++
 .../resources/pack_compensation_scenario.feature   |  42 +++
 .../pack_post_car_exception_scenario.feature       |  43 +++
 .../test/resources/pack_success_scenario.feature   |  41 ++
 .../test/resources/pack_timeout_scenario.feature   |  48 +++
 10 files changed, 922 insertions(+)

diff --git a/acceptance-tests/acceptance-pack-spring-demo-with-nacos/pom.xml 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/pom.xml
new file mode 100644
index 0000000..f558dd1
--- /dev/null
+++ b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/pom.xml
@@ -0,0 +1,414 @@
+<?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>acceptance-tests</artifactId>
+    <groupId>org.apache.servicecomb.pack</groupId>
+    <version>0.5.0-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+
+  <artifactId>acceptance-pack-spring-with-nacos</artifactId>
+  <name>Pack:Acceptance Tests::Spring with nacos</name>
+
+  <dependencies>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-core</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+      <version>${jackson.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.byteman</groupId>
+      <artifactId>byteman-submit</artifactId>
+      <version>${byteman.version}</version>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+    <profile>
+      <id>jdk9</id>
+      <activation>
+        <jdk>[9,)</jdk>
+      </activation>
+      <!-- TODO using jdk argLine to get rid of the jaxb dependencies -->
+      <properties>
+        <jdk.argLine>--add-modules java.xml.bind</jdk.argLine>
+      </properties>
+      <dependencies>
+        <dependency>
+          <groupId>javax.xml.bind</groupId>
+          <artifactId>jaxb-api</artifactId>
+          <version>${jaxb.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>com.sun.xml.bind</groupId>
+          <artifactId>jaxb-impl</artifactId>
+          <version>${jaxb.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.glassfish.jaxb</groupId>
+          <artifactId>jaxb-runtime</artifactId>
+          <version>${jaxb.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>javax.activation</groupId>
+          <artifactId>activation</artifactId>
+          <version>${javax.activation.version}</version>
+        </dependency>
+      </dependencies>
+    </profile>
+    <profile>
+      <id>docker</id>
+      <activation>
+        <file>
+          <exists>/var/run/docker.sock</exists>
+        </file>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>io.fabric8</groupId>
+            <artifactId>docker-maven-plugin</artifactId>
+            <configuration>
+              <showLogs>true</showLogs>
+              <images>
+                <image>
+                  <name>nacos/nacos-server</name>
+                  <alias>nacos</alias>
+                  <run>
+                    <env>
+                      <MODE>standalone</MODE>
+                    </env>
+                    <wait>
+                      <log>Synced node info</log>
+                      <tcp>
+                        <ports>
+                          <port>8848</port>
+                        </ports>
+                      </tcp>
+                      <time>60000</time>
+                    </wait>
+                    <ports>
+                      <port>nacos.port:8848</port>
+                    </ports>
+                  </run>
+                </image>
+                <image>
+                  <name>postgres</name>
+                  <alias>postgres</alias>
+                  <run>
+                    <env>
+                      <POSTGRES_DB>saga</POSTGRES_DB>
+                      <POSTGRES_USER>saga</POSTGRES_USER>
+                      <POSTGRES_PASSWORD>password</POSTGRES_PASSWORD>
+                    </env>
+                    <wait>
+                      <log>database system is ready to accept connections</log>
+                      <tcp>
+                        <ports>
+                          <port>5432</port>
+                        </ports>
+                      </tcp>
+                      <time>60000</time>
+                    </wait>
+                    <ports>
+                      <port>postgres.port:5432</port>
+                    </ports>
+                  </run>
+                </image>
+                <image>
+                  <name>alpha-server:${project.version}</name>
+                  <alias>alpha</alias>
+                  <run>
+                    <env>
+                      <JAVA_OPTS>
+                        -Dspring.profiles.active=prd,test
+                      </JAVA_OPTS>
+                      
<spring.cloud.nacos.discovery.enabled>true</spring.cloud.nacos.discovery.enabled>
+                      
<spring.cloud.nacos.discovery.serverAddr>nacos.servicecomb.io:8848</spring.cloud.nacos.discovery.serverAddr>
+                      <nacos.client.enabled>true</nacos.client.enabled>
+                    </env>
+                    <links>
+                      <link>postgres:postgresql.servicecomb.io</link>
+                      <link>nacos:nacos.servicecomb.io</link>
+                    </links>
+                    <wait>
+                      <log>Started [a-zA-Z]+ in [0-9.]+ seconds</log>
+                      <tcp>
+                        <ports>
+                          <port>8080</port>
+                          <port>8090</port>
+                        </ports>
+                      </tcp>
+                      <time>120000</time>
+                    </wait>
+                    <ports>
+                      <port>alpha.port:8080</port>
+                      <port>alpha.rest.port:8090</port>
+                    </ports>
+                    <dependsOn>
+                      <container>postgres</container>
+                    </dependsOn>
+                  </run>
+                </image>
+                <image>
+                  <name>car:${project.version}</name>
+                  <alias>car</alias>
+                  <run>
+                    <env>
+                      <JAVA_OPTS>
+                        -Dorg.jboss.byteman.debug=true 
-Dorg.jboss.byteman.verbose=true
+                        
-javaagent:/maven/saga/byteman.jar=port:9091,address:0.0.0.0,listener:true
+                      </JAVA_OPTS>
+                      
<spring.cloud.nacos.discovery.enabled>true</spring.cloud.nacos.discovery.enabled>
+                      
<alpha.cluster.register.type>nacos</alpha.cluster.register.type>
+                      
<spring.cloud.nacos.discovery.serverAddr>nacos.servicecomb.io:8848</spring.cloud.nacos.discovery.serverAddr>
+                    </env>
+                    <wait>
+                      <log>Started [a-zA-Z]+ in [0-9.]+ seconds</log>
+                      <tcp>
+                        <ports>
+                          <port>8080</port>
+                          <port>9091</port>
+                        </ports>
+                      </tcp>
+                      <time>120000</time>
+                    </wait>
+                    <links>
+                      <link>alpha:alpha-server.servicecomb.io</link>
+                      <link>nacos:nacos.servicecomb.io</link>
+                    </links>
+                    <ports>
+                      <port>car.port:8080</port>
+                      <port>car.byteman.port:9091</port>
+                    </ports>
+                    <dependsOn>
+                      <container>alpha</container>
+                    </dependsOn>
+                  </run>
+                </image>
+                <image>
+                  <name>hotel:${project.version}</name>
+                  <alias>hotel</alias>
+                  <run>
+                    <env>
+                      <JAVA_OPTS>
+                        -Dorg.jboss.byteman.debug=true 
-Dorg.jboss.byteman.verbose=true
+                        
-javaagent:/maven/saga/byteman.jar=port:9091,address:0.0.0.0,listener:true
+                      </JAVA_OPTS>
+                      
<spring.cloud.nacos.discovery.enabled>true</spring.cloud.nacos.discovery.enabled>
+                      
<alpha.cluster.register.type>nacos</alpha.cluster.register.type>
+                      
<spring.cloud.nacos.discovery.serverAddr>nacos.servicecomb.io:8848</spring.cloud.nacos.discovery.serverAddr>
+                    </env>
+                    <wait>
+                      <log>Started [a-zA-Z]+ in [0-9.]+ seconds</log>
+                      <tcp>
+                        <ports>
+                          <port>8080</port>
+                          <port>9091</port>
+                        </ports>
+                      </tcp>
+                      <time>120000</time>
+                    </wait>
+                    <links>
+                      <link>alpha:alpha-server.servicecomb.io</link>
+                      <link>nacos:nacos.servicecomb.io</link>
+                    </links>
+                    <ports>
+                      <port>hotel.port:8080</port>
+                      <port>hotel.byteman.port:9091</port>
+                    </ports>
+                    <dependsOn>
+                      <container>alpha</container>
+                    </dependsOn>
+                  </run>
+                </image>
+                <image>
+                  <name>booking:${project.version}</name>
+                  <alias>booking</alias>
+                  <run>
+                    <env>
+                      <JAVA_OPTS>
+                        -Dorg.jboss.byteman.debug=true 
-Dorg.jboss.byteman.verbose=true
+                        
-javaagent:/maven/saga/byteman.jar=port:9091,address:0.0.0.0,listener:true
+                      </JAVA_OPTS>
+                      
<spring.cloud.nacos.discovery.enabled>true</spring.cloud.nacos.discovery.enabled>
+                      
<alpha.cluster.register.type>nacos</alpha.cluster.register.type>
+                      
<spring.cloud.nacos.discovery.serverAddr>nacos.servicecomb.io:8848</spring.cloud.nacos.discovery.serverAddr>
+                    </env>
+                    <wait>
+                      <log>Started [a-zA-Z]+ in [0-9.]+ seconds</log>
+                      <tcp>
+                        <ports>
+                          <port>8080</port>
+                          <port>9091</port>
+                        </ports>
+                      </tcp>
+                      <time>120000</time>
+                    </wait>
+                    <links>
+                      <link>alpha:alpha-server.servicecomb.io</link>
+                      <link>car:car.servicecomb.io</link>
+                      <link>hotel:hotel.servicecomb.io</link>
+                      <link>nacos:nacos.servicecomb.io</link>
+                    </links>
+                    <ports>
+                      <port>booking.port:8080</port>
+                      <port>booking.byteman.port:9091</port>
+                    </ports>
+                    <dependsOn>
+                      <container>alpha</container>
+                    </dependsOn>
+                  </run>
+                </image>
+              </images>
+            </configuration>
+            <executions>
+              <execution>
+                <id>start</id>
+                <phase>pre-integration-test</phase>
+                <goals>
+                  <goal>start</goal>
+                </goals>
+              </execution>
+              <execution>
+                <id>stop</id>
+                <phase>post-integration-test</phase>
+                <goals>
+                  <goal>stop</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.codehaus.gmaven</groupId>
+            <artifactId>gmaven-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>add-default-properties</id>
+                <phase>initialize</phase>
+                <goals>
+                  <goal>execute</goal>
+                </goals>
+                <configuration>
+                  <source>
+                    project.properties.setProperty('docker.hostname', 
'localhost')
+                    log.info("Docker hostname is " + 
project.properties['docker.hostname'])
+                  </source>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-failsafe-plugin</artifactId>
+            <version>${maven.failsafe.version}</version>
+            <configuration>
+              <systemPropertyVariables>
+                <alpha.cluster.address>
+                  http://${docker.hostname}:${alpha.port}
+                </alpha.cluster.address>
+                <alpha.rest.address>
+                  http://${docker.hostname}:${alpha.rest.port}
+                </alpha.rest.address>
+                <car.service.address>
+                  http://${docker.hostname}:${car.port}
+                </car.service.address>
+                <hotel.service.address>
+                  http://${docker.hostname}:${hotel.port}
+                </hotel.service.address>
+                <booking.service.address>
+                  http://${docker.hostname}:${booking.port}
+                </booking.service.address>
+                <spring.datasource.url>
+                  
jdbc:postgresql://${docker.hostname}:${postgres.port}/saga?useSSL=false
+                </spring.datasource.url>
+                <byteman.address>
+                  ${docker.hostname}
+                </byteman.address>
+                <car.byteman.port>
+                  ${car.byteman.port}
+                </car.byteman.port>
+                <hotel.byteman.port>
+                  ${hotel.byteman.port}
+                </hotel.byteman.port>
+                <booking.byteman.port>
+                  ${booking.byteman.port}
+                </booking.byteman.port>
+                <info.service.uri>
+                  ${info.service.uri}
+                </info.service.uri>
+              </systemPropertyVariables>
+              <argLine>${jacoco.failsafe.argLine}</argLine>
+            </configuration>
+            <executions>
+              <execution>
+                <goals>
+                  <goal>integration-test</goal>
+                  <goal>verify</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>com.ethlo.persistence.tools</groupId>
+            <artifactId>eclipselink-maven-plugin</artifactId>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>docker-machine</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.gmaven</groupId>
+            <artifactId>gmaven-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>add-dynamic-properties</id>
+                <phase>prepare-package</phase>
+                <goals>
+                  <goal>execute</goal>
+                </goals>
+                <configuration>
+                  <source>
+                    def process = "docker-machine ip default".execute()
+                    process.waitFor()
+                    project.properties.setProperty('docker.hostname', 
process.in.text.trim())
+
+                    log.info("Docker hostname is " + 
project.properties['docker.hostname'])
+                  </source>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>
diff --git 
a/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/java/org/apache/servicecomb/pack/PackStepdefs.java
 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/java/org/apache/servicecomb/pack/PackStepdefs.java
new file mode 100644
index 0000000..711edd2
--- /dev/null
+++ 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/java/org/apache/servicecomb/pack/PackStepdefs.java
@@ -0,0 +1,211 @@
+/*
+ * 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.pack;
+
+import static io.restassured.RestAssured.given;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.commons.lang3.StringUtils.isEmpty;
+import static org.awaitility.Awaitility.await;
+import static org.hamcrest.core.Is.is;
+
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Consumer;
+
+import org.jboss.byteman.agent.submit.Submit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.restassured.response.Response;
+import cucumber.api.DataTable;
+import cucumber.api.java.After;
+import cucumber.api.java8.En;
+
+public class PackStepdefs implements En {
+  private static final Logger LOG = 
LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+
+  private static final String ALPHA_REST_ADDRESS = "alpha.rest.address";
+  private static final String CAR_SERVICE_ADDRESS = "car.service.address";
+  private static final String HOTEL_SERVICE_ADDRESS = "hotel.service.address";
+  private static final String BOOKING_SERVICE_ADDRESS = 
"booking.service.address";
+  private static final String INFO_SERVICE_URI = "info.service.uri";
+  private static final String[] addresses = {CAR_SERVICE_ADDRESS, 
HOTEL_SERVICE_ADDRESS};
+
+  private static final Consumer<Map<String, String>[]> NO_OP_CONSUMER = 
(dataMap) -> {
+  };
+
+  private static final Map<String, Submit> submits = new HashMap<>();
+
+  public PackStepdefs() {
+    Given("^Car Service is up and running$", () -> {
+      probe(System.getProperty(CAR_SERVICE_ADDRESS));
+    });
+
+    And("^Hotel Service is up and running$", () -> {
+      probe(System.getProperty(HOTEL_SERVICE_ADDRESS));
+    });
+
+    And("^Booking Service is up and running$", () -> {
+      probe(System.getProperty(BOOKING_SERVICE_ADDRESS));
+    });
+
+    And("^Alpha is up and running$", () -> {
+      probe(System.getProperty(ALPHA_REST_ADDRESS));
+    });
+
+    Given("^Install the byteman script ([A-Za-z0-9_\\.]+) to ([A-Za-z]+) 
Service$", (String script, String service) -> {
+      LOG.info("Install the byteman script {} to {} service", script, service);
+      List<String> rules = new ArrayList<>();
+      rules.add("target/test-classes/" + script);
+      Submit bm = getBytemanSubmit(service);
+      bm.addRulesFromFiles(rules);
+    });
+
+    When("^User ([A-Za-z]+) requests to book ([0-9]+) cars and ([0-9]+) rooms 
(success|fail)$", (username, cars, rooms, result) -> {
+      LOG.info("Received request from user {} to book {} cars and {} rooms", 
username, cars, rooms);
+
+      Response resp = given()
+          .pathParam("name", username)
+          .pathParam("rooms", rooms)
+          .pathParam("cars", cars)
+          .when()
+          .post(System.getProperty("booking.service.address") + 
"/booking/{name}/{rooms}/{cars}");
+      if (result.equals("success")) {
+        resp.then().statusCode(is(200));
+      } else if (result.equals("fail")) {
+        resp.then().statusCode(is(500));
+      }
+    });
+
+    Then("^Alpha records the following events$", (DataTable dataTable) -> {
+      Consumer<Map<String, String>[]> columnStrippingConsumer = dataMap -> {
+        for (Map<String, String> map : dataMap)
+          map.keySet().retainAll(dataTable.topCells());
+      };
+
+      dataMatches(System.getProperty(ALPHA_REST_ADDRESS) + "/saga/events", 
dataTable, columnStrippingConsumer);
+    });
+
+    And("^Car Service contains the following booking orders$", (DataTable 
dataTable) -> {
+      dataMatches(System.getProperty(CAR_SERVICE_ADDRESS) + "/bookings", 
dataTable, NO_OP_CONSUMER);
+    });
+
+    And("^Hotel Service contains the following booking orders$", (DataTable 
dataTable) -> {
+      dataMatches(System.getProperty(HOTEL_SERVICE_ADDRESS) + "/bookings", 
dataTable, NO_OP_CONSUMER);
+    });
+  }
+
+  @After
+  public void cleanUp() {
+    LOG.info("Cleaning up services");
+    for (String address : addresses) {
+      given()
+          .when()
+          .delete(System.getProperty(address) + "/bookings")
+          .then()
+          .statusCode(is(200));
+    }
+
+    given()
+        .when()
+        .delete(System.getProperty(ALPHA_REST_ADDRESS) + "/saga/events")
+        .then()
+        .statusCode(is(200));
+
+    for (Submit bm : submits.values()) {
+      try {
+        bm.deleteAllRules();
+      } catch (Exception e) {
+        LOG.warn("Fail to delete the byteman rules " + e);
+      }
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  private void dataMatches(String address, DataTable dataTable, 
Consumer<Map<String, String>[]> dataProcessor) {
+    List<Map<String, String>> expectedMaps = dataTable.asMaps(String.class, 
String.class);
+    List<Map<String, String>> actualMaps = new ArrayList<>();
+
+    await().atMost(5, SECONDS).until(() -> {
+      actualMaps.clear();
+      Collections.addAll(actualMaps, retrieveDataMaps(address, dataProcessor));
+      // write the log if the Map size is not same
+      boolean result = expectedMaps.size() == actualMaps.size();
+      if (!result) {
+        LOG.warn("The response message size is not we expected. ExpectedMap 
size is {},  ActualMap size is {}", expectedMaps.size(), actualMaps.size());
+      }
+      return expectedMaps.size() == actualMaps.size();
+    });
+
+    if (expectedMaps.isEmpty() && actualMaps.isEmpty()) {
+      return;
+    }
+
+    LOG.info("Retrieved data {} from service", actualMaps);
+    dataTable.diff(DataTable.create(actualMaps));
+  }
+
+  @SuppressWarnings("unchecked")
+  private Map<String, String>[] retrieveDataMaps(String address, 
Consumer<Map<String, String>[]> dataProcessor) {
+    Map<String, String>[] dataMap = given()
+        .when()
+        .get(address)
+        .then()
+        .statusCode(is(200))
+        .extract()
+        .body()
+        .as(Map[].class);
+
+    dataProcessor.accept(dataMap);
+    return dataMap;
+  }
+
+  private void probe(String address) {
+    String infoURI = System.getProperty(INFO_SERVICE_URI);
+    if (isEmpty(infoURI)) {
+      infoURI = "/info";
+    }
+    LOG.info("The info service uri is " + infoURI);
+    probe(address, infoURI);
+  }
+
+  private void probe(String address, String infoURI) {
+    LOG.info("Connecting to service address {}", address);
+    given()
+        .when()
+        .get(address + infoURI)
+        .then()
+        .statusCode(is(200));
+  }
+
+  private Submit getBytemanSubmit(String service) {
+    if (submits.containsKey(service)) {
+      return submits.get(service);
+    } else {
+      String address = System.getProperty("byteman.address");
+      String port = System.getProperty(service.toLowerCase() + 
".byteman.port");
+      Submit bm = new Submit(address, Integer.parseInt(port));
+      submits.put(service, bm);
+      return bm;
+    }
+  }
+}
diff --git 
a/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/java/org/apache/servicecomb/pack/RunCucumberIT.java
 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/java/org/apache/servicecomb/pack/RunCucumberIT.java
new file mode 100644
index 0000000..c8415ce
--- /dev/null
+++ 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/java/org/apache/servicecomb/pack/RunCucumberIT.java
@@ -0,0 +1,29 @@
+/*
+ * 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.pack;
+
+import org.junit.runner.RunWith;
+
+import cucumber.api.CucumberOptions;
+import cucumber.api.junit.Cucumber;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(plugin = {"pretty", "html:target/cucumber"},
+    features = "src/test/resources")
+public class RunCucumberIT {
+}
diff --git 
a/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/booking_exception.btm
 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/booking_exception.btm
new file mode 100644
index 0000000..5afea45
--- /dev/null
+++ 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/booking_exception.btm
@@ -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.
+
+##############################################################
+# rules to timeout the booking after invoking the services
+#
+###############################################################
+
+RULE throw exception
+CLASS org.apache.servicecomb.pack.demo.booking.BookingController
+METHOD postCarBooking
+AT ENTRY
+IF TRUE
+DO debug("throw RuntimeException here"),
+   throw new RuntimeException("Cannot access the booking hotel server!")
+ENDRULE
diff --git 
a/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/booking_timeout.btm
 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/booking_timeout.btm
new file mode 100644
index 0000000..829e7ba
--- /dev/null
+++ 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/booking_timeout.btm
@@ -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.
+
+##############################################################
+# rules to timeout the booking after invoking the services
+#
+###############################################################
+
+RULE set the saga timeout to 5s
+INTERFACE org.apache.servicecomb.pack.omega.context.annotations.SagaStart
+METHOD timeout
+AT EXIT
+IF TRUE
+DO RETURN 5
+ENDRULE
+
+RULE sleep when postBooking until timeout happens
+CLASS org.apache.servicecomb.pack.demo.booking.BookingController
+METHOD postBooking
+AT ENTRY
+IF TRUE
+DO debug("delay 10s until the booking timeout"),
+   Thread.sleep(10000)
+ENDRULE
diff --git 
a/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/log4j2-test.xml
 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/log4j2-test.xml
new file mode 100644
index 0000000..58924c6
--- /dev/null
+++ 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/log4j2-test.xml
@@ -0,0 +1,30 @@
+<?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 status="WARN">
+  <Appenders>
+    <Console name="Console" target="SYSTEM_OUT">
+      <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - 
%msg%n"/>
+    </Console>
+  </Appenders>
+  <Loggers>
+    <Root level="info">
+      <AppenderRef ref="Console"/>
+    </Root>
+  </Loggers>
+</Configuration>
diff --git 
a/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_compensation_scenario.feature
 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_compensation_scenario.feature
new file mode 100644
index 0000000..daa086f
--- /dev/null
+++ 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_compensation_scenario.feature
@@ -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.
+
+Feature: Alpha records transaction events
+
+  Scenario: A sub-transaction failed and global transaction compensated
+    Given Car Service is up and running
+    And Hotel Service is up and running
+    And Booking Service is up and running
+    And Alpha is up and running
+
+    When User Sean requests to book 5 cars and 3 rooms fail
+
+    Then Alpha records the following events
+      | serviceName  | type               |
+      | booking | SagaStartedEvent   |
+      | car     | TxStartedEvent     |
+      | car     | TxEndedEvent       |
+      | hotel   | TxStartedEvent     |
+      | hotel   | TxAbortedEvent     |
+      | booking | TxAbortedEvent     |
+      | car     | TxCompensatedEvent |
+      | car     | SagaEndedEvent     |
+    
+    Then Car Service contains the following booking orders
+      | id | name | amount | confirmed | cancelled |
+      | 1  | Sean | 5      | false     | true      |
+
+    Then Hotel Service contains the following booking orders
+      | id | name | amount | confirmed | cancelled |
diff --git 
a/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_post_car_exception_scenario.feature
 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_post_car_exception_scenario.feature
new file mode 100644
index 0000000..c5f3249
--- /dev/null
+++ 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_post_car_exception_scenario.feature
@@ -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.
+
+Feature: Alpha records transaction events
+
+  Scenario: An exception is throw and the first transaction should be 
compensated
+    Given Car Service is up and running
+    And Hotel Service is up and running
+    And Booking Service is up and running
+    And Alpha is up and running
+
+    Given Install the byteman script booking_exception.btm to Booking Service
+
+    When User Sean requests to book 1 cars and 1 rooms fail
+
+    Then Alpha records the following events
+      | serviceName  | type               |
+      | booking | SagaStartedEvent   |
+      | car     | TxStartedEvent     |
+      | car     | TxEndedEvent       |
+      | booking | TxAbortedEvent     |
+      | car     | TxCompensatedEvent |
+      | car     | SagaEndedEvent     |
+
+    Then Car Service contains the following booking orders
+      | id | name | amount | confirmed | cancelled |
+      | 1  | Sean | 1      | false     | true      |
+
+    Then Hotel Service contains the following booking orders
+      | id | name | amount | confirmed | cancelled |
+    
diff --git 
a/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_success_scenario.feature
 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_success_scenario.feature
new file mode 100644
index 0000000..b7d4048
--- /dev/null
+++ 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_success_scenario.feature
@@ -0,0 +1,41 @@
+# 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.
+
+Feature: Alpha records transaction events
+
+  Scenario: Everything is normal
+    Given Car Service is up and running
+    And Hotel Service is up and running
+    And Booking Service is up and running
+    And Alpha is up and running
+
+    When User Sean requests to book 2 cars and 1 rooms success
+
+    Then Alpha records the following events
+      | serviceName  | type             |
+      | booking | SagaStartedEvent |
+      | car     | TxStartedEvent   |
+      | car     | TxEndedEvent     |
+      | hotel   | TxStartedEvent   |
+      | hotel   | TxEndedEvent     |
+      | booking | SagaEndedEvent   |
+
+    And Car Service contains the following booking orders
+      | id | name | amount | confirmed | cancelled |
+      | 1  | Sean | 2      | true      | false     |
+
+    And Hotel Service contains the following booking orders
+      | id | name | amount | confirmed | cancelled |
+      | 1  | Sean | 1      | true      | false     |
diff --git 
a/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_timeout_scenario.feature
 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_timeout_scenario.feature
new file mode 100644
index 0000000..1b545b1
--- /dev/null
+++ 
b/acceptance-tests/acceptance-pack-spring-demo-with-nacos/src/test/resources/pack_timeout_scenario.feature
@@ -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.
+
+Feature: Alpha records transaction events
+
+  Scenario: A transaction timeout and will be compensated
+    Given Car Service is up and running
+    And Hotel Service is up and running
+    And Booking Service is up and running
+    And Alpha is up and running
+
+    Given Install the byteman script booking_timeout.btm to Booking Service
+
+    When User Sean requests to book 1 cars and 1 rooms fail
+
+    Then Alpha records the following events
+      | serviceName  | type          |
+      | booking | SagaStartedEvent   |
+      | car     | TxStartedEvent     |
+      | car     | TxEndedEvent       |
+      | hotel   | TxStartedEvent     |
+      | hotel   | TxEndedEvent       |
+      | booking | TxAbortedEvent     |
+      | hotel   | TxCompensatedEvent |
+      | car     | TxCompensatedEvent |
+      | car     | SagaEndedEvent   |
+
+
+    Then Car Service contains the following booking orders
+      | id | name | amount | confirmed | cancelled |
+      | 1  | Sean | 1      | false     | true      |
+
+    Then Hotel Service contains the following booking orders
+      | id | name | amount | confirmed | cancelled |
+      | 1  | Sean | 1      | false     | true      |
+

Reply via email to