This is an automated email from the ASF dual-hosted git repository.
zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 3be122fabb2 Add EtcdDistributedLockTest (#37649)
3be122fabb2 is described below
commit 3be122fabb2b66f48193e678683322bd38373765
Author: Liang Zhang <[email protected]>
AuthorDate: Mon Jan 5 19:14:42 2026 +0800
Add EtcdDistributedLockTest (#37649)
* Add more test cases on Presto SQL parser
* Add EtcdDistributedLockTest
---
.../cluster/etcd/lock/EtcdDistributedLockTest.java | 120 +++++++++++++++++++++
1 file changed, 120 insertions(+)
diff --git
a/mode/type/cluster/repository/provider/etcd/src/test/java/org/apache/shardingsphere/mode/repository/cluster/etcd/lock/EtcdDistributedLockTest.java
b/mode/type/cluster/repository/provider/etcd/src/test/java/org/apache/shardingsphere/mode/repository/cluster/etcd/lock/EtcdDistributedLockTest.java
new file mode 100644
index 00000000000..00e72436a79
--- /dev/null
+++
b/mode/type/cluster/repository/provider/etcd/src/test/java/org/apache/shardingsphere/mode/repository/cluster/etcd/lock/EtcdDistributedLockTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.shardingsphere.mode.repository.cluster.etcd.lock;
+
+import io.etcd.jetcd.ByteSequence;
+import io.etcd.jetcd.Client;
+import io.etcd.jetcd.Lease;
+import io.etcd.jetcd.Lock;
+import io.etcd.jetcd.lease.LeaseGrantResponse;
+import io.etcd.jetcd.lock.LockResponse;
+import io.etcd.jetcd.lock.UnlockResponse;
+import
org.apache.shardingsphere.mode.repository.cluster.etcd.props.EtcdProperties;
+import
org.apache.shardingsphere.mode.repository.cluster.etcd.props.EtcdPropertyKey;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+class EtcdDistributedLockTest {
+
+ @Mock
+ private Client client;
+
+ @Mock
+ private Lock lock;
+
+ @Mock
+ private Lease lease;
+
+ @Mock
+ private EtcdProperties etcdProps;
+
+ @BeforeEach
+ void setUp() {
+ when(client.getLockClient()).thenReturn(lock);
+ when(client.getLeaseClient()).thenReturn(lease);
+
when(etcdProps.getValue(EtcdPropertyKey.TIME_TO_LIVE_SECONDS)).thenReturn(1);
+ }
+
+ @Test
+ void assertTryLockSuccess() {
+ when(lease.grant(1)).thenReturn(CompletableFuture.completedFuture(new
LeaseGrantResponse(io.etcd.jetcd.api.LeaseGrantResponse.newBuilder().setID(1L).build())));
+ when(lock.lock(any(ByteSequence.class),
eq(1L))).thenReturn(CompletableFuture.completedFuture(mock(LockResponse.class)));
+ assertTrue(new EtcdDistributedLock("foo_lock", client,
etcdProps).tryLock(50L));
+ ArgumentCaptor<ByteSequence> lockKeyCaptor =
ArgumentCaptor.forClass(ByteSequence.class);
+ verify(lock).lock(lockKeyCaptor.capture(), eq(1L));
+ assertThat(new String(lockKeyCaptor.getValue().getBytes(),
StandardCharsets.UTF_8), is("foo_lock"));
+ }
+
+ @Test
+ void assertTryLockInterrupted() throws ExecutionException,
InterruptedException {
+ CompletableFuture<LeaseGrantResponse> leaseGrantFuture =
mock(CompletableFuture.class);
+ when(leaseGrantFuture.get()).thenThrow(InterruptedException.class);
+ when(lease.grant(1)).thenReturn(leaseGrantFuture);
+ assertFalse(new EtcdDistributedLock("foo_lock", client,
etcdProps).tryLock(20L));
+ assertTrue(Thread.currentThread().isInterrupted());
+ Thread.interrupted();
+ }
+
+ @Test
+ void assertTryLockOnExecutionException() {
+ when(lease.grant(1)).thenReturn(CompletableFuture.completedFuture(new
LeaseGrantResponse(io.etcd.jetcd.api.LeaseGrantResponse.newBuilder().setID(1L).build())));
+ CompletableFuture<LockResponse> lockFuture = new CompletableFuture<>();
+ lockFuture.completeExceptionally(new RuntimeException("lock failure"));
+ when(lock.lock(any(ByteSequence.class),
eq(1L))).thenReturn(lockFuture);
+ assertFalse(new EtcdDistributedLock("foo_lock", client,
etcdProps).tryLock(10L));
+ assertFalse(Thread.currentThread().isInterrupted());
+ }
+
+ @Test
+ void assertUnlockSuccess() {
+
when(lock.unlock(any(ByteSequence.class))).thenReturn(CompletableFuture.completedFuture(mock(UnlockResponse.class)));
+ new EtcdDistributedLock("foo_lock", client, etcdProps).unlock();
+ ArgumentCaptor<ByteSequence> lockKeyCaptor =
ArgumentCaptor.forClass(ByteSequence.class);
+ verify(lock).unlock(lockKeyCaptor.capture());
+ assertThat(new String(lockKeyCaptor.getValue().getBytes(),
StandardCharsets.UTF_8), is("foo_lock"));
+ }
+
+ @Test
+ void assertUnlockInterrupted() throws ExecutionException,
InterruptedException {
+ CompletableFuture<UnlockResponse> unlockFuture =
mock(CompletableFuture.class);
+ when(unlockFuture.get()).thenThrow(new InterruptedException());
+ when(lock.unlock(any(ByteSequence.class))).thenReturn(unlockFuture);
+ new EtcdDistributedLock("foo_lock", client, etcdProps).unlock();
+ assertTrue(Thread.currentThread().isInterrupted());
+ Thread.interrupted();
+ }
+}