Skip to content

Commit 2637ac3

Browse files
author
chengliefeng
committed
feature: add TCC three-phase hooks (apache#6731)
1 parent 381c3c3 commit 2637ac3

File tree

2 files changed

+182
-138
lines changed

2 files changed

+182
-138
lines changed

integration-tx-api/src/test/java/org/apache/seata/integration/tx/api/fence/hook/TccHookTest.java

Lines changed: 0 additions & 138 deletions
This file was deleted.
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package org.apache.seata.rm.tcc;
2+
3+
import java.lang.reflect.Field;
4+
import java.lang.reflect.Method;
5+
import java.util.Map;
6+
import java.util.concurrent.ConcurrentHashMap;
7+
8+
import org.apache.seata.common.executor.Callback;
9+
import org.apache.seata.core.exception.TransactionException;
10+
import org.apache.seata.core.model.BranchType;
11+
import org.apache.seata.integration.tx.api.fence.hook.TccHook;
12+
import org.apache.seata.integration.tx.api.fence.hook.TccHookManager;
13+
import org.apache.seata.integration.tx.api.interceptor.ActionInterceptorHandler;
14+
import org.apache.seata.integration.tx.api.interceptor.TwoPhaseBusinessActionParam;
15+
import org.apache.seata.rm.tcc.api.BusinessActionContext;
16+
import org.apache.seata.core.model.Resource;
17+
import org.junit.jupiter.api.BeforeEach;
18+
import org.junit.jupiter.api.Test;
19+
import org.mockito.Mockito;
20+
21+
22+
import static org.mockito.Mockito.mock;
23+
import static org.mockito.Mockito.verify;
24+
25+
public class TccHookTest {
26+
private TccHook tccHook;
27+
private String xid;
28+
private Long branchId;
29+
private String actionName;
30+
private BusinessActionContext context;
31+
private TestActionInterceptorHandler actionInterceptorHandler;
32+
private TCCResourceManager tccResourceManager;
33+
34+
@BeforeEach
35+
public void setUp() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException {
36+
tccHook = mock(TccHook.class);
37+
xid = "test-xid";
38+
branchId = 12345L;
39+
actionName = "testAction";
40+
context = new BusinessActionContext();
41+
TccHookManager.clear();
42+
TccHookManager.registerHook(tccHook);
43+
44+
actionInterceptorHandler = Mockito.spy(new TestActionInterceptorHandler());
45+
TCCResourceManager tccResourceManagerObject = new TCCResourceManager();
46+
TCCResource tccResource = mock(TCCResource.class);
47+
Mockito.doReturn(actionName)
48+
.when(tccResource).getResourceId();
49+
Mockito.doReturn(actionName)
50+
.when(tccResource).getActionName();
51+
TestTccThreePhaseHandler testTccThreePhaseHandler = new TestTccThreePhaseHandler();
52+
Mockito.doReturn(testTccThreePhaseHandler)
53+
.when(tccResource).getTargetBean();
54+
55+
Mockito.doReturn(new String[0])
56+
.when(tccResource).getPhaseTwoCommitKeys();
57+
Mockito.doReturn(new Class[0])
58+
.when(tccResource).getCommitArgsClasses();
59+
60+
Mockito.doReturn(new String[0])
61+
.when(tccResource).getPhaseTwoRollbackKeys();
62+
Mockito.doReturn(new Class[0])
63+
.when(tccResource).getRollbackArgsClasses();
64+
65+
Method commitMethod = testTccThreePhaseHandler.getClass().getMethod("commit");
66+
Mockito.doReturn(commitMethod)
67+
.when(tccResource).getCommitMethod();
68+
69+
Method rollbackMethod = testTccThreePhaseHandler.getClass().getMethod("rollback");
70+
Mockito.doReturn(rollbackMethod)
71+
.when(tccResource).getRollbackMethod();
72+
73+
Map<String, Resource> tccResourceCache = new ConcurrentHashMap<>();
74+
tccResourceCache.put(actionName, tccResource);
75+
setPrivateField(tccResourceManagerObject, "tccResourceCache", tccResourceCache);
76+
tccResourceManagerObject.registerResource();
77+
tccResourceManager = Mockito.spy(tccResourceManagerObject);
78+
}
79+
80+
@Test
81+
public void testBeforeTccPrepare() {
82+
for (TccHook hook : TccHookManager.getHooks()) {
83+
hook.beforeTccPrepare(xid, branchId, actionName, context);
84+
}
85+
verify(tccHook).beforeTccPrepare(xid, branchId, actionName, context);
86+
}
87+
88+
@Test
89+
public void testAfterTccPrepare() {
90+
for (TccHook hook : TccHookManager.getHooks()) {
91+
hook.afterTccPrepare(xid, branchId, actionName, context);
92+
}
93+
verify(tccHook).afterTccPrepare(xid, branchId, actionName, context);
94+
}
95+
96+
@Test
97+
public void testBeforeTccCommit() {
98+
for (TccHook hook : TccHookManager.getHooks()) {
99+
hook.beforeTccCommit(xid, branchId, actionName, context);
100+
}
101+
verify(tccHook).beforeTccCommit(xid, branchId, actionName, context);
102+
}
103+
104+
@Test
105+
public void testAfterTccCommit() {
106+
for (TccHook hook : TccHookManager.getHooks()) {
107+
hook.afterTccCommit(xid, branchId, actionName, context);
108+
}
109+
verify(tccHook).afterTccCommit(xid, branchId, actionName, context);
110+
}
111+
112+
@Test
113+
public void testBeforeTccRollback() {
114+
for (TccHook hook : TccHookManager.getHooks()) {
115+
hook.beforeTccRollback(xid, branchId, actionName, context);
116+
}
117+
verify(tccHook).beforeTccRollback(xid, branchId, actionName, context);
118+
}
119+
120+
@Test
121+
public void testAfterTccRollback() {
122+
for (TccHook hook : TccHookManager.getHooks()) {
123+
hook.afterTccRollback(xid, branchId, actionName, context);
124+
}
125+
verify(tccHook).afterTccRollback(xid, branchId, actionName, context);
126+
}
127+
128+
@Test
129+
public void testTccPrepareHook() throws Throwable {
130+
TestTccThreePhaseHandler testTccThreePhaseHandler = new TestTccThreePhaseHandler();
131+
Method method = testTccThreePhaseHandler.getClass().getMethod("prepare");
132+
TwoPhaseBusinessActionParam twoPhaseBusinessActionParam = Mockito.mock(TwoPhaseBusinessActionParam.class);
133+
Callback<Object> callback = Mockito.mock(Callback.class, Mockito.withSettings().defaultAnswer(Mockito.RETURNS_DEFAULTS));
134+
Mockito.doReturn(actionName)
135+
.when(twoPhaseBusinessActionParam).getActionName();
136+
actionInterceptorHandler.proceed(method, null, xid, twoPhaseBusinessActionParam, callback);
137+
verify(tccHook).beforeTccPrepare(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
138+
verify(tccHook).afterTccPrepare(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
139+
}
140+
141+
@Test
142+
public void testTccCommitHook() throws TransactionException {
143+
tccResourceManager.branchCommit(BranchType.TCC, xid, branchId, actionName, null);
144+
verify(tccHook).beforeTccCommit(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
145+
verify(tccHook).afterTccCommit(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
146+
}
147+
148+
@Test
149+
public void testTccRollbackHook() throws TransactionException {
150+
tccResourceManager.branchRollback(BranchType.TCC, xid, branchId, actionName, null);
151+
verify(tccHook).beforeTccRollback(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
152+
verify(tccHook).afterTccRollback(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any());
153+
}
154+
155+
private void setPrivateField(Object target, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
156+
Field field = target.getClass().getDeclaredField(fieldName);
157+
field.setAccessible(true);
158+
field.set(target, value);
159+
}
160+
161+
public class TestActionInterceptorHandler extends ActionInterceptorHandler {
162+
@Override
163+
public BusinessActionContext getOrCreateActionContextAndResetToArguments(Class<?>[] parameterTypes, Object[] arguments) {
164+
return context;
165+
}
166+
167+
@Override
168+
public String doTxActionLogStore(Method method, Object[] arguments, TwoPhaseBusinessActionParam businessActionParam,
169+
BusinessActionContext actionContext) {
170+
return String.valueOf(branchId);
171+
}
172+
}
173+
174+
public class TestTccThreePhaseHandler {
175+
public void prepare() {
176+
}
177+
public void commit() {
178+
}
179+
public void rollback() {
180+
}
181+
}
182+
}

0 commit comments

Comments
 (0)