Skip to content
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
569241e
fix: correct JUnit 5 lifecycle method visibility
contrueCT Sep 13, 2025
13b93a3
Fix JUnit 5 lifecycle method visibility in changelog
contrueCT Sep 13, 2025
85f24e2
Fix JUnit 5 lifecycle method visibility in changelog
contrueCT Sep 13, 2025
0e3d952
Merge remote-tracking branch 'origin/patch-1' into 2.x
contrueCT Sep 13, 2025
aa5114a
Merge remote-tracking branch 'origin/patch-2' into 2.x
contrueCT Sep 13, 2025
a7d4b12
Update pull request reference in 2.x.md
contrueCT Sep 13, 2025
6554f46
Update pull request reference in 2.x.md
contrueCT Sep 13, 2025
b4dfb3a
fix: correct JUnit test method access modifiers and annotations
contrueCT Sep 14, 2025
c518bb3
Merge remote-tracking branch 'origin/2.x' into 2.x
contrueCT Sep 14, 2025
6f7990c
fix JUnit test method access modifiers and annotations in changelog
contrueCT Sep 15, 2025
ad95dfc
refactor: migrate EtcdRegistryServiceImplTest from JUnit 4 to JUnit 5
contrueCT Sep 15, 2025
53dfaa2
Merge branch '2.x' into 2.x
xingfudeshi Sep 18, 2025
033c627
fix: format code by spotless
contrueCT Sep 18, 2025
dab561a
Merge remote-tracking branch 'origin/2.x' into 2.x
contrueCT Sep 18, 2025
3cf788e
Merge branch '2.x' into 2.x
contrueCT Sep 18, 2025
9d2baee
Merge branch '2.x' into 2.x
contrueCT Sep 23, 2025
54f9a30
Merge branch '2.x' into 2.x
xingfudeshi Sep 24, 2025
6e403e3
fix: correct updateSql assignment in DATE_TYPE and BINARY_TYPE test c…
contrueCT Sep 24, 2025
4117cd8
Merge remote-tracking branch 'origin/2.x' into 2.x
contrueCT Sep 24, 2025
6c2af4e
Merge branch '2.x' into 2.x
slievrly Sep 29, 2025
7adbefb
Merge branch '2.x' into 2.x
contrueCT Oct 16, 2025
1716ed2
Merge branch '2.x' into 2.x
slievrly Oct 17, 2025
ac9973c
Merge branch '2.x' into 2.x
YongGoose Oct 17, 2025
9d2a0b3
fix:fix the Spotless issues
contrueCT Oct 18, 2025
44011fd
fix:fix the Spotless issues
contrueCT Oct 18, 2025
2c9e734
Merge branch '2.x' into 2.x
contrueCT Oct 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changes/en-us/2.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Add changes here for all PR submitted to the 2.x branch.

### test:

- [[#7635](https://github.com/apache/incubator-seata/pull/7635)] fix JUnit test method access modifiers and annotations
- [[#7541](https://github.com/seata/seata/pull/7541)] fix jakarta UT failed in jdk17+
- [[#7540](https://github.com/seata/seata/pull/7540)] fix port of mock server
- [[#7580](https://github.com/seata/seata/pull/7580)] fix the exception caused by the disorder of test case execution order
Expand Down Expand Up @@ -116,6 +117,7 @@ Thanks to these contributors for their code commits. Please report an unintended
- [WangzJi](https://github.com/WangzJi)
- [unifolio0](https://github.com/unifolio0)
- [Asuka-star](https://github.com/Asuka-star)
- [contrueCT](https://github.com/contrueCT)
- [YoWuwuuuw](https://github.com/YoWuwuuuw)
- [jongmin-chung](https://github.com/jongmin-chung)
- [jihun4452](https://github.com/jihun4452)
Expand Down
2 changes: 2 additions & 0 deletions changes/zh-cn/2.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@

### test:

- [[#7635](https://github.com/apache/incubator-seata/pull/7635)] 修正 JUnit 5 测试方法的访问修饰符及注解使用规范
- [[#7541](https://github.com/seata/seata/pull/7541)] 修复 jakarta 依赖在 jdk17+ 单测失败问题
- [[#7540](https://github.com/seata/seata/pull/7540)] 修复mock server端口冲突问题
- [[#7578](https://github.com/seata/seata/pull/7578)] zstd解压由jni改为ZstdInputStream
Expand Down Expand Up @@ -113,6 +114,7 @@
- [WangzJi](https://github.com/WangzJi)
- [unifolio0](https://github.com/unifolio0)
- [Asuka-star](https://github.com/Asuka-star)
- [contrueCT](https://github.com/contrueCT)
- [YoWuwuuuw](https://github.com/YoWuwuuuw)
- [jongmin-chung](https://github.com/jongmin-chung)
- [jihun4452](https://github.com/jihun4452)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,23 @@

import io.etcd.jetcd.ByteSequence;
import io.etcd.jetcd.Client;
import io.etcd.jetcd.KV;
import io.etcd.jetcd.Watch;
import io.etcd.jetcd.launcher.junit4.EtcdClusterResource;
import io.etcd.jetcd.launcher.EtcdCluster;
import io.etcd.jetcd.launcher.EtcdClusterFactory;
import io.etcd.jetcd.options.DeleteOption;
import io.etcd.jetcd.options.GetOption;
import io.etcd.jetcd.watch.WatchResponse;
import org.apache.seata.discovery.registry.RegistryService;
import org.junit.Rule;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import java.net.InetSocketAddress;
import java.net.URI;
import java.util.List;
import java.util.concurrent.TimeUnit;

Expand All @@ -42,34 +46,54 @@
public class EtcdRegistryServiceImplTest {
private static final String REGISTRY_KEY_PREFIX = "registry-seata-";
private static final String CLUSTER_NAME = "default";

@Rule
private static final EtcdClusterResource etcd = new EtcdClusterResource(CLUSTER_NAME, 1);

private final Client client =
Client.builder().endpoints(etcd.getClientEndpoints()).build();
private static final String HOST = "127.0.0.1";
private static final int PORT = 8091;

private static EtcdCluster etcd;
private static Client client;
private static List<URI> clientEndpoints;

@BeforeAll
public static void beforeClass() throws Exception {
System.setProperty(
EtcdRegistryServiceImpl.TEST_ENDPONT,
etcd.getClientEndpoints().get(0).toString());
public static void beforeAll() {
etcd = EtcdClusterFactory.buildCluster(CLUSTER_NAME, 1, false);
etcd.start();
clientEndpoints = etcd.getClientEndpoints();
client = Client.builder().endpoints(clientEndpoints).build();
}

@AfterAll
public static void afterClass() throws Exception {
System.setProperty(EtcdRegistryServiceImpl.TEST_ENDPONT, "");
public static void afterAll() {
if (client != null) {
client.close();
}
if (etcd != null) {
etcd.close();
}
System.clearProperty(EtcdRegistryServiceImpl.TEST_ENDPONT);
}

@BeforeEach
public void setUp() {
String endpoint = clientEndpoints.get(0).toString();
System.setProperty(EtcdRegistryServiceImpl.TEST_ENDPONT, endpoint);
}

@AfterEach
public void tearDown() throws Exception {
KV kvClient = client.getKVClient();
ByteSequence keyPrefix = buildRegistryKeyPrefix();
DeleteOption deleteOption =
DeleteOption.newBuilder().withPrefix(keyPrefix).build();
kvClient.delete(keyPrefix, deleteOption).get();
}

@Test
public void testRegister() throws Exception {
RegistryService registryService = new EtcdRegistryProvider().provide();
InetSocketAddress inetSocketAddress = new InetSocketAddress(HOST, PORT);
// 1.register
// 1. Register the service instance.
registryService.register(inetSocketAddress);
// 2.get instance information
// 2. Verify the registration by directly querying etcd.
GetOption getOption =
GetOption.newBuilder().withPrefix(buildRegistryKeyPrefix()).build();
long count = client.getKVClient().get(buildRegistryKeyPrefix(), getOption).get().getKvs().stream()
Expand All @@ -87,7 +111,7 @@ public void testUnregister() throws Exception {
InetSocketAddress inetSocketAddress = new InetSocketAddress(HOST, PORT);
// 1.register
registryService.register(inetSocketAddress);
// 2.get instance information
// 2. Verify it was registered successfully.
GetOption getOption =
GetOption.newBuilder().withPrefix(buildRegistryKeyPrefix()).build();
long count = client.getKVClient().get(buildRegistryKeyPrefix(), getOption).get().getKvs().stream()
Expand All @@ -97,10 +121,9 @@ public void testUnregister() throws Exception {
})
.count();
assertThat(count).isEqualTo(1);
// 3.unregister
// 3. Unregister the instance.
registryService.unregister(inetSocketAddress);
// 4.again get instance information
getOption = GetOption.newBuilder().withPrefix(buildRegistryKeyPrefix()).build();
// 4. Verify it was successfully removed from etcd.
count = client.getKVClient().get(buildRegistryKeyPrefix(), getOption).get().getKvs().stream()
.filter(keyValue -> {
String[] instanceInfo = keyValue.getValue().toString(UTF_8).split(":");
Expand All @@ -118,8 +141,8 @@ public void testSubscribe() throws Exception {
registryService.register(inetSocketAddress);
// 2.subscribe
EtcdListener etcdListener = new EtcdListener();
registryService.subscribe(CLUSTER_NAME, etcdListener);
// 3.delete instance,see if the listener can be notified
registryService.subscribe(DEFAULT_TX_GROUP, etcdListener);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, was there any particular reason for using DEFAULT_TX_GROUP instead of CLUSTER_NAME?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! The subscribe() and lookup() methods expect a transaction service group, not an etcd cluster name.
The original code had mismatched key paths:

  • Registration: registry-seata-<DEFAULT_TX_GROUP>/...
  • Subscription: registry-seata-<CLUSTER_NAME>/...

Even though both values were "default", using DEFAULT_TX_GROUP is semantically correct and matches how Seata actually works - clients look up services by transaction group.

// 3. Delete the instance key and verify the listener is notified.
DeleteOption deleteOption =
DeleteOption.newBuilder().withPrefix(buildRegistryKeyPrefix()).build();
client.getKVClient().delete(buildRegistryKeyPrefix(), deleteOption).get();
Expand All @@ -134,14 +157,14 @@ public void testUnsubscribe() throws Exception {
registryService.register(inetSocketAddress);
// 2.subscribe
EtcdListener etcdListener = new EtcdListener();
registryService.subscribe(CLUSTER_NAME, etcdListener);
registryService.subscribe(DEFAULT_TX_GROUP, etcdListener);
// 3.delete instance,see if the listener can be notified
DeleteOption deleteOption =
DeleteOption.newBuilder().withPrefix(buildRegistryKeyPrefix()).build();
client.getKVClient().delete(buildRegistryKeyPrefix(), deleteOption).get();
assertThat(etcdListener.isNotified()).isTrue();
// 4.unsubscribe
registryService.unsubscribe(CLUSTER_NAME, etcdListener);
registryService.unsubscribe(DEFAULT_TX_GROUP, etcdListener);
// 5.reset
etcdListener.reset();
// 6.put instance,the listener should not be notified
Expand All @@ -159,47 +182,56 @@ public void testLookup() throws Exception {
registryService.register(inetSocketAddress);
// 2.lookup
List<InetSocketAddress> inetSocketAddresses = registryService.lookup(DEFAULT_TX_GROUP);
assertThat(inetSocketAddresses).size().isEqualTo(1);
// 3.Verify that the correct instance is returned.
assertThat(inetSocketAddresses).hasSize(1);
assertThat(inetSocketAddresses.get(0).getAddress().getHostAddress()).isEqualTo(HOST);
assertThat(inetSocketAddresses.get(0).getPort()).isEqualTo(PORT);
}

/**
* build registry key prefix
*
* @return
* Builds the etcd key prefix for a given service group.
* The key prefix includes the transaction service group as is standard in Seata.
* @return ByteSequence of the prefix
*/
private ByteSequence buildRegistryKeyPrefix() {
return ByteSequence.from(REGISTRY_KEY_PREFIX, UTF_8);
return ByteSequence.from(REGISTRY_KEY_PREFIX + DEFAULT_TX_GROUP, UTF_8);
}

/**
* etcd listener
* Listener implementation for testing subscription notifications.
*/
private static class EtcdListener implements Watch.Listener {
private boolean notified = false;
private volatile boolean notified = false;

@Override
public void onNext(WatchResponse response) {
notified = true;
}

@Override
public void onError(Throwable throwable) {}
public void onError(Throwable throwable) {
// No-op for this test
}

@Override
public void onCompleted() {}
public void onCompleted() {
// No-op for this test
}

/**
* @return
* Waits for a short period to allow the async notification to arrive.
* @return true if a notification was received.
*/
public boolean isNotified() throws InterruptedException {
TimeUnit.SECONDS.sleep(3);
// Give some time for the watch event to be processed
TimeUnit.SECONDS.sleep(1);
return notified;
}

/**
* reset
* Resets the notification flag for subsequent assertions.
*/
private void reset() {
public void reset() {
this.notified = false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public static void stop() {
}

@BeforeEach
private void prepareTable() {
public void prepareTable() {
execSQL("DROP TABLE IF EXISTS table_name");
execSQL("CREATE TABLE table_name ( `id` int(8), `name` varchar(64), PRIMARY KEY (`id`))");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class ParameterParserTest extends BaseSpringBootTest {
* init
*/
@BeforeEach
private void init() {
public void init() {
String[] args = new String[] {"-h", "127.0.0.1", "-p", "8088", "-m", "file", "-e", "test"};
parameterParser = new ParameterParser(args);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ public void doType(int sqlType, int type, boolean globalCommit) throws Throwable
testTypeSql(sqlType, globalCommit, sqlClass.getInsertSql(), sqlClass.getTableName(), sqlClass.getUpdateSql());
}

@Test
public void testTypeSql(int sqlType, boolean globalCommit, String insertSql, String tableName, String updateSql)
throws Throwable {
doExecute(sqlType, insertSql);
Expand Down Expand Up @@ -249,12 +248,13 @@ private SqlClass dogetType(int sqlType, int type) {
case 3:
sqlClass.setInsertSql(TEST_DATE_TYPE_INSERT_SQL);
sqlClass.setTableName(DATE_TABLE_NAME);
sqlClass.setTableName(TEST_DATE_TYPE_UPDATE_SQL);
sqlClass.setUpdateSql(TEST_DATE_TYPE_UPDATE_SQL);
break;
case 4:
sqlClass.setInsertSql(TEST_BINARY_TYPE_INSERT_SQL);
sqlClass.setTableName(BINARY_TABLE_NAME);
sqlClass.setTableName(TEST_BINARY_TYPE_UPDATE_SQL);
sqlClass.setUpdateSql(TEST_BINARY_TYPE_UPDATE_SQL);
break;
default:
}
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ public void doType(int type, boolean globalCommit) throws Throwable {
testTypeSql(ORACLE, globalCommit, insertSql, tableName, updateSql);
}

@Test
public void testTypeSql(int sqlType, boolean globalCommit, String insertSql, String tableName, String updateSql)
throws Throwable {
doExecute(sqlType, insertSql);
Expand Down
Loading