From 980a2f4302ed88f28d3eb4e4de49dee59b886cac Mon Sep 17 00:00:00 2001 From: A Cabbage <928124786@qq.com> Date: Sun, 27 Oct 2024 00:05:29 +0800 Subject: [PATCH] feat: add springboot-seata and springboot-mybatis-seata e2e case (#697) --- .../e2e-files/sqlsh/all.sql | 56 ++++++++ .../e2e-files/success.yaml | 1 + .../e2e-replace/application.properties | 10 ++ .../e2e-replace/file.conf | 126 ++++++++++++++++++ .../springboot-mybatis-seata/seata-e2e.yaml | 58 ++++++++ .../seata/SpringbootSeataApplication.java | 15 ++- .../java/org/apache/seata/e2e/E2EUtil.java | 22 +++ .../springboot-seata/e2e-files/sqlsh/all.sql | 56 ++++++++ .../springboot-seata/e2e-files/success.yaml | 1 + .../e2e-replace/application.properties | 10 ++ .../springboot-seata/e2e-replace/file.conf | 126 ++++++++++++++++++ at-sample/springboot-seata/seata-e2e.yaml | 58 ++++++++ .../seata/SpringbootSeataApplication.java | 15 ++- .../java/org/apache/seata/e2e/E2EUtil.java | 22 +++ .../apache/seata/builder/ImageBuilder.java | 2 +- 15 files changed, 575 insertions(+), 3 deletions(-) create mode 100644 at-sample/springboot-mybatis-seata/e2e-files/sqlsh/all.sql create mode 100644 at-sample/springboot-mybatis-seata/e2e-files/success.yaml create mode 100644 at-sample/springboot-mybatis-seata/e2e-replace/application.properties create mode 100644 at-sample/springboot-mybatis-seata/e2e-replace/file.conf create mode 100644 at-sample/springboot-mybatis-seata/seata-e2e.yaml create mode 100644 at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/e2e/E2EUtil.java create mode 100644 at-sample/springboot-seata/e2e-files/sqlsh/all.sql create mode 100644 at-sample/springboot-seata/e2e-files/success.yaml create mode 100644 at-sample/springboot-seata/e2e-replace/application.properties create mode 100644 at-sample/springboot-seata/e2e-replace/file.conf create mode 100644 at-sample/springboot-seata/seata-e2e.yaml create mode 100644 at-sample/springboot-seata/src/main/java/org/apache/seata/e2e/E2EUtil.java diff --git a/at-sample/springboot-mybatis-seata/e2e-files/sqlsh/all.sql b/at-sample/springboot-mybatis-seata/e2e-files/sqlsh/all.sql new file mode 100644 index 000000000..877dc39b8 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/e2e-files/sqlsh/all.sql @@ -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. +-- + +CREATE TABLE `account_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `money` int(11) DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE `stock_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE KEY `commodity_code` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE `order_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT '0', + `money` int(11) DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `undo_log` +( + `branch_id` BIGINT NOT NULL COMMENT 'branch transaction id', + `xid` VARCHAR(128) NOT NULL COMMENT 'global transaction id', + `context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization', + `rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info', + `log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status', + `log_created` DATETIME(6) NOT NULL COMMENT 'create datetime', + `log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime', + UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) +) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table'; +ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`); \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/e2e-files/success.yaml b/at-sample/springboot-mybatis-seata/e2e-files/success.yaml new file mode 100644 index 000000000..946b0e70c --- /dev/null +++ b/at-sample/springboot-mybatis-seata/e2e-files/success.yaml @@ -0,0 +1 @@ +{"res": "success"} \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/e2e-replace/application.properties b/at-sample/springboot-mybatis-seata/e2e-replace/application.properties new file mode 100644 index 000000000..6b1c0ad93 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/e2e-replace/application.properties @@ -0,0 +1,10 @@ +spring.application.name=springboot-mybatis-seata +server.port=8088 +spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://mysqlAddress:3306/seata?useSSL=false&useUnicode=true&characterEncoding=UTF8 +spring.datasource.username=user +spring.datasource.password=123456 +seata.application-id=springboot-mybatis-seata +seata.tx-service-group=my_test_tx_group +mybatis.configuration.map-underscore-to-camel-case=true +mybatis.mapper-locations=classpath:mapper/*.xml \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/e2e-replace/file.conf b/at-sample/springboot-mybatis-seata/e2e-replace/file.conf new file mode 100644 index 000000000..cf8230524 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/e2e-replace/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "seata:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/springboot-mybatis-seata/seata-e2e.yaml b/at-sample/springboot-mybatis-seata/seata-e2e.yaml new file mode 100644 index 000000000..23f4b39f9 --- /dev/null +++ b/at-sample/springboot-mybatis-seata/seata-e2e.yaml @@ -0,0 +1,58 @@ +e2e: + scene_name: at-springboot-mybatis-seata + # retry config + retry: + max: 5 + interval: 10s + total_timeout: 10m + # services in docker-compose + modules: + # provider service + providers: + - name: springboot-mybatis-seata + docker_service: + hostname: springboot-mybatis-seata + restart: on-failure + container_name: test + depends_on: + mysql: + condition: service_healthy + environment: + E2E_ENV: open + # infrastructure services + infrastructures: + - name: mysql + docker_service: + hostname: mysqlAddress + image: mysql:5.7 + volumes: + - ./e2e-files/sqlsh:/docker-entrypoint-initdb.d + restart: always + environment: + MYSQL_ROOT_PASSWORD: 123456 + MYSQL_DATABASE: seata + MYSQL_USER: user + MYSQL_PASSWORD: 123456 + healthcheck: + test: '[ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]' + interval: 5s + timeout: 10s + retries: 10 + - name: seata-server + docker_service: + hostname: seata + image: apache/seata-server:2.1.0 + environment: + SEATA_PORT: 8091 + STORE_MODE: file + replace: + - source: e2e-replace/application.properties + dest: src/main/resources/application.properties + - source: e2e-replace/file.conf + dest: src/main/resources/file.conf + + # cases to verify + cases: + - name: normal test rollback + invoke: 'docker exec test cat result.yaml' + verify: './e2e-files/success.yaml' \ No newline at end of file diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java index d8a4255e0..c59c226d9 100644 --- a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java @@ -16,6 +16,7 @@ */ package org.apache.seata; +import org.apache.seata.e2e.E2EUtil; import org.apache.seata.service.BusinessService; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; @@ -33,7 +34,19 @@ public static void main(String[] args) throws Exception { BusinessService businessService = BEAN_FACTORY.getBean(BusinessService.class); - Thread thread = new Thread(() -> businessService.purchase(TestData.USER_ID, TestData.COMMODITY_CODE, 2)); + Thread thread = new Thread(() -> { + String res = "{\"res\": \"success\"}"; + try { + businessService.purchase(TestData.USER_ID, TestData.COMMODITY_CODE, 1); + if (E2EUtil.isInE2ETest()) { + E2EUtil.writeE2EResFile(res); + } + } catch (Exception e) { + if (E2EUtil.isInE2ETest() && "random exception mock!".equals(e.getMessage())) { + E2EUtil.writeE2EResFile(res); + } + } + }); thread.start(); //keep run diff --git a/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/e2e/E2EUtil.java b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/e2e/E2EUtil.java new file mode 100644 index 000000000..140b6ce9b --- /dev/null +++ b/at-sample/springboot-mybatis-seata/src/main/java/org/apache/seata/e2e/E2EUtil.java @@ -0,0 +1,22 @@ +package org.apache.seata.e2e; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Map; + +public class E2EUtil { + public static void writeE2EResFile(String outPutRes) { + try { + Files.write(Paths.get("result.yaml"), outPutRes.getBytes()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static boolean isInE2ETest() { + Map envs = System.getenv(); + String env = envs.getOrDefault("E2E_ENV", ""); + return "open".equals(env); + } +} diff --git a/at-sample/springboot-seata/e2e-files/sqlsh/all.sql b/at-sample/springboot-seata/e2e-files/sqlsh/all.sql new file mode 100644 index 000000000..877dc39b8 --- /dev/null +++ b/at-sample/springboot-seata/e2e-files/sqlsh/all.sql @@ -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. +-- + +CREATE TABLE `account_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `money` int(11) DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE `stock_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT '0', + PRIMARY KEY (`id`), + UNIQUE KEY `commodity_code` (`commodity_code`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE `order_tbl` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` varchar(255) DEFAULT NULL, + `commodity_code` varchar(255) DEFAULT NULL, + `count` int(11) DEFAULT '0', + `money` int(11) DEFAULT '0', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `undo_log` +( + `branch_id` BIGINT NOT NULL COMMENT 'branch transaction id', + `xid` VARCHAR(128) NOT NULL COMMENT 'global transaction id', + `context` VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization', + `rollback_info` LONGBLOB NOT NULL COMMENT 'rollback info', + `log_status` INT(11) NOT NULL COMMENT '0:normal status,1:defense status', + `log_created` DATETIME(6) NOT NULL COMMENT 'create datetime', + `log_modified` DATETIME(6) NOT NULL COMMENT 'modify datetime', + UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`) +) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table'; +ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`); \ No newline at end of file diff --git a/at-sample/springboot-seata/e2e-files/success.yaml b/at-sample/springboot-seata/e2e-files/success.yaml new file mode 100644 index 000000000..946b0e70c --- /dev/null +++ b/at-sample/springboot-seata/e2e-files/success.yaml @@ -0,0 +1 @@ +{"res": "success"} \ No newline at end of file diff --git a/at-sample/springboot-seata/e2e-replace/application.properties b/at-sample/springboot-seata/e2e-replace/application.properties new file mode 100644 index 000000000..a5d8d5957 --- /dev/null +++ b/at-sample/springboot-seata/e2e-replace/application.properties @@ -0,0 +1,10 @@ +spring.application.name=springboot-seata +server.port=8088 +spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver +spring.datasource.url=jdbc:mysql://mysqlAddress:3306/seata?useSSL=false&useUnicode=true&characterEncoding=UTF8 +spring.datasource.username=user +spring.datasource.password=123456 +seata.application-id=springboot-seata +seata.tx-service-group=my_test_tx_group +mybatis.configuration.map-underscore-to-camel-case=true +mybatis.mapper-locations=classpath:mapper/*.xml \ No newline at end of file diff --git a/at-sample/springboot-seata/e2e-replace/file.conf b/at-sample/springboot-seata/e2e-replace/file.conf new file mode 100644 index 000000000..cf8230524 --- /dev/null +++ b/at-sample/springboot-seata/e2e-replace/file.conf @@ -0,0 +1,126 @@ +# +# 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. +# + +transport { + # tcp, unix-domain-socket + type = "TCP" + #NIO, NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the tm client batch send request enable + enableTmClientBatchSendRequest = false + # the rm client batch send request enable + enableRmClientBatchSendRequest = true + # the rm client rpc request timeout + rpcRmRequestTimeout = 2000 + # the tm client rpc request timeout + rpcTmRequestTimeout = 30000 + # the rm client rpc request timeout + rpcRmRequestTimeout = 15000 + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "seata:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + tableMetaCheckerInterval = 60000 + reportSuccessEnable = false + sagaBranchRegisterEnable = false + sagaJsonParser = "fastjson" + sagaRetryPersistModeUpdate = false + sagaCompensatePersistModeUpdate = false + tccActionInterceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + sqlParserType = "druid" + branchExecutionTimeoutXA = 60000 + connectionTwoPhaseHoldTimeoutXA = 10000 + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + defaultGlobalTransactionTimeout = 60000 + degradeCheck = false + degradeCheckPeriod = 2000 + degradeCheckAllowTimes = 10 + interceptorOrder = -2147482648 #Ordered.HIGHEST_PRECEDENCE + 1000 + } + undo { + dataValidation = true + onlyCareUpdateColumns = true + logSerialization = "jackson" + logTable = "undo_log" + compress { + enable = true + # allow zip, gzip, deflater, lz4, bzip2, zstd default is zip + type = zip + # if rollback info size > threshold, then will be compress + # allow k m g t + threshold = 64k + } + } + loadBalance { + type = "XID" + virtualNodes = 10 + } +} +log { + exceptionRate = 100 +} +tcc { + fence { + # tcc fence log table name + logTableName = tcc_fence_log + # tcc fence log clean period + cleanPeriod = 1h + } +} diff --git a/at-sample/springboot-seata/seata-e2e.yaml b/at-sample/springboot-seata/seata-e2e.yaml new file mode 100644 index 000000000..e0b0a8528 --- /dev/null +++ b/at-sample/springboot-seata/seata-e2e.yaml @@ -0,0 +1,58 @@ +e2e: + scene_name: at-springboot-seata + # retry config + retry: + max: 5 + interval: 10s + total_timeout: 10m + # services in docker-compose + modules: + # provider service + providers: + - name: springboot-seata + docker_service: + hostname: springboot-seata + restart: on-failure + container_name: test + depends_on: + mysql: + condition: service_healthy + environment: + E2E_ENV: open + # infrastructure services + infrastructures: + - name: mysql + docker_service: + hostname: mysqlAddress + image: mysql:5.7 + volumes: + - ./e2e-files/sqlsh:/docker-entrypoint-initdb.d + restart: always + environment: + MYSQL_ROOT_PASSWORD: 123456 + MYSQL_DATABASE: seata + MYSQL_USER: user + MYSQL_PASSWORD: 123456 + healthcheck: + test: '[ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]' + interval: 5s + timeout: 10s + retries: 10 + - name: seata-server + docker_service: + hostname: seata + image: apache/seata-server:2.1.0 + environment: + SEATA_PORT: 8091 + STORE_MODE: file + replace: + - source: e2e-replace/application.properties + dest: src/main/resources/application.properties + - source: e2e-replace/file.conf + dest: src/main/resources/file.conf + + # cases to verify + cases: + - name: normal test rollback + invoke: 'docker exec test cat result.yaml' + verify: './e2e-files/success.yaml' \ No newline at end of file diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java index 32dc50aa3..dae72f3dc 100644 --- a/at-sample/springboot-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/SpringbootSeataApplication.java @@ -1,5 +1,6 @@ package org.apache.seata; +import org.apache.seata.e2e.E2EUtil; import org.apache.seata.service.BusinessService; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactory; @@ -17,7 +18,19 @@ public static void main(String[] args) throws Exception { BusinessService businessService = BEAN_FACTORY.getBean(BusinessService.class); - Thread thread = new Thread(() -> businessService.purchase("U100001", "C00321", 2)); + Thread thread = new Thread(() -> { + String res = "{\"res\": \"success\"}"; + try { + businessService.purchase("U100001", "C00321", 2); + if (E2EUtil.isInE2ETest()) { + E2EUtil.writeE2EResFile(res); + } + } catch (Exception e) { + if (E2EUtil.isInE2ETest() && "random exception mock!".equals(e.getMessage())) { + E2EUtil.writeE2EResFile(res); + } + } + }); thread.start(); //keep run diff --git a/at-sample/springboot-seata/src/main/java/org/apache/seata/e2e/E2EUtil.java b/at-sample/springboot-seata/src/main/java/org/apache/seata/e2e/E2EUtil.java new file mode 100644 index 000000000..140b6ce9b --- /dev/null +++ b/at-sample/springboot-seata/src/main/java/org/apache/seata/e2e/E2EUtil.java @@ -0,0 +1,22 @@ +package org.apache.seata.e2e; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Map; + +public class E2EUtil { + public static void writeE2EResFile(String outPutRes) { + try { + Files.write(Paths.get("result.yaml"), outPutRes.getBytes()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static boolean isInE2ETest() { + Map envs = System.getenv(); + String env = envs.getOrDefault("E2E_ENV", ""); + return "open".equals(env); + } +} diff --git a/e2e-test/e2e-test-builder/src/main/java/org/apache/seata/builder/ImageBuilder.java b/e2e-test/e2e-test-builder/src/main/java/org/apache/seata/builder/ImageBuilder.java index f26c06550..27832635c 100644 --- a/e2e-test/e2e-test-builder/src/main/java/org/apache/seata/builder/ImageBuilder.java +++ b/e2e-test/e2e-test-builder/src/main/java/org/apache/seata/builder/ImageBuilder.java @@ -154,7 +154,7 @@ private void runDockerBuild(E2EConfig e2EConfig) throws IOException, Interrupted printProcessLog(LOGGER, process); int exitCode = process.waitFor(); if (exitCode != 0) { - LOGGER.warn(String.format("Docker image for module %s build failed with exit code %d", module.getName(), exitCode)); + LOGGER.error(String.format("Docker image for module %s build failed with exit code %d", module.getName(), exitCode)); } } }