You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2018/08/23 09:12:31 UTC
[incubator-servicecomb-saga] 01/01: SCB-817 Added the unit tests of
TCC related Aspect
This is an automated email from the ASF dual-hosted git repository.
ningjiang pushed a commit to branch SCB-817
in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-saga.git
commit 5e5aadef15cbd69f6c04dcb575f12ef6fce6f697
Author: Willem Jiang <ji...@huawei.com>
AuthorDate: Thu Aug 23 16:42:40 2018 +0800
SCB-817 Added the unit tests of TCC related Aspect
---
.../omega/transaction/tcc/TccEventService.java | 2 -
.../transaction/tcc/TccParticipatorAspect.java | 8 +-
.../tcc/TccStartAnnotationProcessor.java | 14 +-
.../saga/omega/transaction/tcc/TccStartAspect.java | 4 +-
.../transaction/tcc/events/ParticipatedEvent.java | 24 +++
.../transaction/tcc/events/TccEndedEvent.java | 14 +-
.../transaction/tcc/events/TccStartedEvent.java | 4 -
.../transaction/tcc/TccParticipatorAspectTest.java | 169 +++++++++++++++++++++
.../tcc/TccStartAnnotationProcessorTest.java | 155 +++++++++++++++++++
.../omega/transaction/tcc/TccStartAspectTest.java | 164 ++++++++++++++++++++
10 files changed, 534 insertions(+), 24 deletions(-)
diff --git a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccEventService.java b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccEventService.java
index a722f49..48ad743 100644
--- a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccEventService.java
+++ b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccEventService.java
@@ -38,7 +38,5 @@ public interface TccEventService {
AlphaResponse TccTransactionStart(TccStartedEvent tccStartEvent);
AlphaResponse TccTransactionStop(TccEndedEvent tccEndEvent);
-
- AlphaResponse send(TxEvent event);
}
diff --git a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccParticipatorAspect.java b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccParticipatorAspect.java
index e64bc2a..a78d819 100644
--- a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccParticipatorAspect.java
+++ b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccParticipatorAspect.java
@@ -61,14 +61,14 @@ public class TccParticipatorAspect {
try {
Object result = joinPoint.proceed();
// Send the participate message back
- tccEventService.participate(new ParticipatedEvent(context.globalTxId(), context.localTxId(), localTxId, cancelMethod, confirmMethod,
- TransactionStatus.Succeed));
+ tccEventService.participate(new ParticipatedEvent(context.globalTxId(), context.localTxId(), localTxId, confirmMethod,
+ cancelMethod, TransactionStatus.Succeed));
LOG.debug("Participate Transaction with context {} has finished.", context);
return result;
} catch (Throwable throwable) {
// Now we don't handle the error message
- tccEventService.participate(new ParticipatedEvent(context.globalTxId(), context.localTxId(), localTxId, cancelMethod,
- confirmMethod, TransactionStatus.Failed));
+ tccEventService.participate(new ParticipatedEvent(context.globalTxId(), context.localTxId(), localTxId, confirmMethod,
+ cancelMethod, TransactionStatus.Failed));
LOG.error("Participate Transaction with context {} failed.", context, throwable);
throw throwable;
} finally {
diff --git a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAnnotationProcessor.java b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAnnotationProcessor.java
index 26621d1..55198dd 100644
--- a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAnnotationProcessor.java
+++ b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAnnotationProcessor.java
@@ -21,13 +21,11 @@ import javax.transaction.TransactionalException;
import org.apache.servicecomb.saga.common.TransactionStatus;
import org.apache.servicecomb.saga.omega.context.OmegaContext;
import org.apache.servicecomb.saga.omega.transaction.AlphaResponse;
-import org.apache.servicecomb.saga.omega.transaction.EventAwareInterceptor;
import org.apache.servicecomb.saga.omega.transaction.OmegaException;
-import org.apache.servicecomb.saga.omega.transaction.TxAbortedEvent;
import org.apache.servicecomb.saga.omega.transaction.tcc.events.TccEndedEvent;
import org.apache.servicecomb.saga.omega.transaction.tcc.events.TccStartedEvent;
-public class TccStartAnnotationProcessor implements EventAwareInterceptor {
+public class TccStartAnnotationProcessor {
private final OmegaContext omegaContext;
private final TccEventService eventService;
@@ -37,9 +35,7 @@ public class TccStartAnnotationProcessor implements EventAwareInterceptor {
this.eventService = eventService;
}
- @Override
- public AlphaResponse preIntercept(String parentTxId, String compensationMethod, int timeout, String retriesMethod,
- int retries, Object... message) {
+ public AlphaResponse preIntercept(String parentTxId, String methodName, int timeout) {
try {
return eventService.TccTransactionStart(new TccStartedEvent(omegaContext.globalTxId(), omegaContext.localTxId()));
} catch (OmegaException e) {
@@ -47,14 +43,12 @@ public class TccStartAnnotationProcessor implements EventAwareInterceptor {
}
}
- @Override
- public void postIntercept(String parentTxId, String compensationMethod) {
+ public void postIntercept(String parentTxId, String methodName) {
eventService.TccTransactionStop(new TccEndedEvent(omegaContext.globalTxId(), omegaContext.localTxId(),
TransactionStatus.Succeed));
}
- @Override
- public void onError(String parentTxId, String compensationMethod, Throwable throwable) {
+ public void onError(String parentTxId, String methodName, Throwable throwable) {
// Send the cancel event
// Do we need to wait for the alpha finish all the transaction
eventService.TccTransactionStop(new TccEndedEvent(omegaContext.globalTxId(), omegaContext.localTxId(),
diff --git a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAspect.java b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAspect.java
index f6d1d77..62a2873 100644
--- a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAspect.java
+++ b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAspect.java
@@ -20,9 +20,7 @@ import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import org.apache.servicecomb.saga.omega.context.OmegaContext;
-import org.apache.servicecomb.saga.omega.context.annotations.SagaStart;
import org.apache.servicecomb.saga.omega.context.annotations.TccStart;
-import org.apache.servicecomb.saga.omega.transaction.MessageSender;
import org.apache.servicecomb.saga.omega.transaction.OmegaException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
@@ -49,7 +47,7 @@ public class TccStartAspect {
initializeOmegaContext();
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
- tccStartAnnotationProcessor.preIntercept(context.globalTxId(), method.toString(), tccStart.timeout(), "", 0);
+ tccStartAnnotationProcessor.preIntercept(context.globalTxId(), method.toString(), tccStart.timeout());
LOG.debug("Initialized context {} before execution of method {}", context, method.toString());
try {
diff --git a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/ParticipatedEvent.java b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/ParticipatedEvent.java
index 3372f8e..ac2dcb9 100644
--- a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/ParticipatedEvent.java
+++ b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/ParticipatedEvent.java
@@ -38,4 +38,28 @@ public class ParticipatedEvent {
this.cancelMethod = cancelMethod;
this.status = status;
}
+
+ public String getGlobalTxId() {
+ return globalTxId;
+ }
+
+ public String getLocalTxId() {
+ return localTxId;
+ }
+
+ public String getParentTxId() {
+ return parentTxId;
+ }
+
+ public String getConfirmMethod() {
+ return confirmMethod;
+ }
+
+ public String getCancelMethod() {
+ return cancelMethod;
+ }
+
+ public TransactionStatus getStatus() {
+ return status;
+ }
}
diff --git a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/TccEndedEvent.java b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/TccEndedEvent.java
index 7c666b2..31a187f 100644
--- a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/TccEndedEvent.java
+++ b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/TccEndedEvent.java
@@ -22,7 +22,19 @@ public class TccEndedEvent {
private final String globalTxId;
private final String localTxId;
private final TransactionStatus status;
-
+
+
+ public String getGlobalTxId() {
+ return globalTxId;
+ }
+
+ public String getLocalTxId() {
+ return localTxId;
+ }
+
+ public TransactionStatus getStatus() {
+ return status;
+ }
public TccEndedEvent(String globalTxId, String localTxId,
TransactionStatus status) {
diff --git a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/TccStartedEvent.java b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/TccStartedEvent.java
index edd0333..8449cb4 100644
--- a/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/TccStartedEvent.java
+++ b/omega/omega-transaction/src/main/java/org/apache/servicecomb/saga/omega/transaction/tcc/events/TccStartedEvent.java
@@ -20,17 +20,13 @@ public class TccStartedEvent {
private final String globalTxId;
private final String localTxId;
-
public String getGlobalTxId() {
return globalTxId;
}
-
public String getLocalTxId() {
return localTxId;
}
-
-
public TccStartedEvent(String globalTxId, String localTxId) {
this.globalTxId = globalTxId;
this.localTxId = localTxId;
diff --git a/omega/omega-transaction/src/test/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccParticipatorAspectTest.java b/omega/omega-transaction/src/test/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccParticipatorAspectTest.java
new file mode 100644
index 0000000..8e6b36e
--- /dev/null
+++ b/omega/omega-transaction/src/test/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccParticipatorAspectTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.saga.omega.transaction.tcc;
+
+import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.servicecomb.saga.common.TransactionStatus;
+import org.apache.servicecomb.saga.omega.context.IdGenerator;
+import org.apache.servicecomb.saga.omega.context.OmegaContext;
+import org.apache.servicecomb.saga.omega.context.annotations.TccStart;
+import org.apache.servicecomb.saga.omega.transaction.AlphaResponse;
+import org.apache.servicecomb.saga.omega.transaction.annotations.Compensable;
+import org.apache.servicecomb.saga.omega.transaction.annotations.Participate;
+import org.apache.servicecomb.saga.omega.transaction.tcc.events.ParticipatedEvent;
+import org.apache.servicecomb.saga.omega.transaction.tcc.events.TccEndedEvent;
+import org.apache.servicecomb.saga.omega.transaction.tcc.events.TccStartedEvent;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TccParticipatorAspectTest {
+ private final ProceedingJoinPoint joinPoint = Mockito.mock(ProceedingJoinPoint.class);
+ private final MethodSignature methodSignature = Mockito.mock(MethodSignature.class);
+ private final String globalTxId = UUID.randomUUID().toString();
+ private final String localTxId = UUID.randomUUID().toString();
+ private final String newLocalTxId = UUID.randomUUID().toString();
+
+ private final List<ParticipatedEvent> participatedEvents = new ArrayList<>();
+ private final AlphaResponse response = new AlphaResponse(false);
+ private final TccEventService eventService = new TccEventService() {
+ @Override
+ public void onConnected() {
+
+ }
+
+ @Override
+ public void onDisconnected() {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+
+ @Override
+ public String target() {
+ return null;
+ }
+
+ @Override
+ public AlphaResponse participate(ParticipatedEvent participateEvent) {
+ participatedEvents.add(participateEvent);
+ return response;
+ }
+
+ @Override
+ public AlphaResponse TccTransactionStart(TccStartedEvent tccStartEvent) {
+ return null;
+ }
+
+ @Override
+ public AlphaResponse TccTransactionStop(TccEndedEvent tccEndEvent) {
+ return null;
+ }
+
+ };
+
+
+ @SuppressWarnings("unchecked")
+ private final IdGenerator<String> idGenerator = Mockito.mock(IdGenerator.class);
+
+ private final OmegaContext omegaContext = new OmegaContext(idGenerator);
+ private final Participate participate = mock(Participate.class);
+
+ private final TccParticipatorAspect aspect = new TccParticipatorAspect(eventService, omegaContext);
+
+
+ @Before
+ public void setUp() throws Exception {
+ when(idGenerator.nextId()).thenReturn(newLocalTxId);
+ when(joinPoint.getSignature()).thenReturn(methodSignature);
+ when(joinPoint.getTarget()).thenReturn(this);
+
+ when(methodSignature.getMethod()).thenReturn(this.getClass().getDeclaredMethod("doNothing"));
+ when(participate.cancelMethod()).thenReturn("cancelMethod");
+ when(participate.confirmMethod()).thenReturn("confirmMethod");
+
+ omegaContext.setGlobalTxId(globalTxId);
+ omegaContext.setLocalTxId(localTxId);
+ }
+
+ @Test
+ public void participateMethodIsCalledSuccessed() throws Throwable {
+ aspect.advise(joinPoint, participate);
+
+ assertThat(participatedEvents.size(), is(1));
+ ParticipatedEvent participatedEvent = participatedEvents.get(0);
+
+ assertThat(participatedEvent.getGlobalTxId(), is(globalTxId));
+ assertThat(participatedEvent.getParentTxId(), is(localTxId));
+ assertThat(participatedEvent.getLocalTxId(), is(newLocalTxId));
+ assertThat(participatedEvent.getStatus(), is(TransactionStatus.Succeed));
+ assertThat(participatedEvent.getCancelMethod(), is("cancelMethod"));
+ assertThat(participatedEvent.getConfirmMethod(), is("confirmMethod"));
+
+ assertThat(omegaContext.globalTxId(), is(globalTxId));
+ assertThat(omegaContext.localTxId(), is(localTxId));
+ }
+
+ @Test
+ public void participateMethodIsCalledFailed() throws Throwable {
+ RuntimeException oops = new RuntimeException("oops");
+
+ when(joinPoint.proceed()).thenThrow(oops);
+
+ try {
+ aspect.advise(joinPoint, participate);
+ expectFailing(RuntimeException.class);
+ } catch (RuntimeException e) {
+ assertThat(e, is(oops));
+ }
+
+ assertThat(participatedEvents.size(), is(1));
+ ParticipatedEvent participatedEvent = participatedEvents.get(0);
+
+ assertThat(participatedEvent.getGlobalTxId(), is(globalTxId));
+ assertThat(participatedEvent.getParentTxId(), is(localTxId));
+ assertThat(participatedEvent.getLocalTxId(), is(newLocalTxId));
+ assertThat(participatedEvent.getStatus(), is(TransactionStatus.Failed));
+ assertThat(participatedEvent.getCancelMethod(), is("cancelMethod"));
+ assertThat(participatedEvent.getConfirmMethod(), is("confirmMethod"));
+
+
+ assertThat(omegaContext.globalTxId(), is(globalTxId));
+ assertThat(omegaContext.localTxId(), is(localTxId));
+ }
+
+ private String doNothing() {
+ return "doNothing";
+ }
+
+}
diff --git a/omega/omega-transaction/src/test/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAnnotationProcessorTest.java b/omega/omega-transaction/src/test/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAnnotationProcessorTest.java
new file mode 100644
index 0000000..95f8137
--- /dev/null
+++ b/omega/omega-transaction/src/test/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAnnotationProcessorTest.java
@@ -0,0 +1,155 @@
+/*
+ * 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.saga.omega.transaction.tcc;
+
+import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import javax.transaction.TransactionalException;
+
+import org.apache.servicecomb.saga.common.TransactionStatus;
+import org.apache.servicecomb.saga.omega.context.IdGenerator;
+import org.apache.servicecomb.saga.omega.context.OmegaContext;
+import org.apache.servicecomb.saga.omega.transaction.AlphaResponse;
+import org.apache.servicecomb.saga.omega.transaction.OmegaException;
+import org.apache.servicecomb.saga.omega.transaction.tcc.events.ParticipatedEvent;
+import org.apache.servicecomb.saga.omega.transaction.tcc.events.TccEndedEvent;
+import org.apache.servicecomb.saga.omega.transaction.tcc.events.TccStartedEvent;
+import org.hamcrest.core.Is;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TccStartAnnotationProcessorTest {
+ private final String globalTxId = UUID.randomUUID().toString();
+ private final AlphaResponse response = new AlphaResponse(false);
+ private final AlphaResponse abortResponse = new AlphaResponse(true);
+ private final List<TccStartedEvent> startedEvents = new ArrayList<>();
+ private final List<TccEndedEvent> endedEvents = new ArrayList<>();
+ private boolean throwException = false;
+
+ private final IdGenerator<String> generator = mock(IdGenerator.class);
+ private final OmegaContext context = new OmegaContext(generator);
+ private final OmegaException exception = new OmegaException("exception", new RuntimeException("runtime exception"));
+ private final TccEventService eventService = new TccEventService() {
+ @Override
+ public void onConnected() {
+
+ }
+
+ @Override
+ public void onDisconnected() {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+
+ @Override
+ public String target() {
+ return null;
+ }
+
+ @Override
+ public AlphaResponse participate(ParticipatedEvent participateEvent) {
+ return null;
+ }
+
+ @Override
+ public AlphaResponse TccTransactionStart(TccStartedEvent tccStartEvent) {
+ if (throwException) {
+ throw exception;
+ }
+ startedEvents.add(tccStartEvent);
+ return response;
+ }
+
+ @Override
+ public AlphaResponse TccTransactionStop(TccEndedEvent tccEndEvent) {
+ endedEvents.add(tccEndEvent);
+ return response;
+ }
+
+
+ };
+ private final TccStartAnnotationProcessor tccStartAnnotationProcessor = new TccStartAnnotationProcessor(context,
+ eventService);
+
+ @Before
+ public void setUp() throws Exception {
+ context.setGlobalTxId(globalTxId);
+ context.setLocalTxId(globalTxId);
+ }
+
+ @Test
+ public void testSendTccStartEvent() {
+ AlphaResponse result = tccStartAnnotationProcessor
+ .preIntercept(null, "TccStartMethod", 0);
+
+ TccStartedEvent event = startedEvents.get(0);
+
+ assertThat(event.getGlobalTxId(), is(globalTxId));
+ assertThat(event.getLocalTxId(), is(globalTxId));
+ assertThat(result, is(response));
+
+ }
+
+ @Test
+ public void testSendTccStartEventFailed() {
+ throwException = true;
+ try {
+ tccStartAnnotationProcessor
+ .preIntercept(null, "TccStartMethod", 0);
+ expectFailing(TransactionalException.class);
+ } catch (TransactionalException e) {
+ Assert.assertThat(e.getMessage(), Is.is("exception"));
+ Assert.assertThat(e.getCause(), instanceOf(RuntimeException.class));
+ Assert.assertThat(e.getCause().getMessage(), Is.is("runtime exception"));
+ }
+
+ }
+
+ @Test
+ public void testSendTccEndEventWithoutError() {
+ tccStartAnnotationProcessor.postIntercept(null, "TccStartMethod");
+
+ TccEndedEvent event = endedEvents.get(0);
+
+ assertThat(event.getGlobalTxId(), is(globalTxId));
+ assertThat(event.getLocalTxId(), is(globalTxId));
+ assertThat(event.getStatus(), is(TransactionStatus.Succeed));
+
+ }
+
+ @Test
+ public void testSendTccEndEventWithError() {
+ tccStartAnnotationProcessor.onError(null, "TccStartMethod", null);
+ TccEndedEvent event = endedEvents.get(0);
+ assertThat(event.getGlobalTxId(), is(globalTxId));
+ assertThat(event.getLocalTxId(), is(globalTxId));
+ assertThat(event.getStatus(), is(TransactionStatus.Failed));
+ }
+}
diff --git a/omega/omega-transaction/src/test/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAspectTest.java b/omega/omega-transaction/src/test/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAspectTest.java
new file mode 100644
index 0000000..005af67
--- /dev/null
+++ b/omega/omega-transaction/src/test/java/org/apache/servicecomb/saga/omega/transaction/tcc/TccStartAspectTest.java
@@ -0,0 +1,164 @@
+/*
+ * 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.saga.omega.transaction.tcc;
+
+import static com.seanyinx.github.unit.scaffolding.AssertUtils.expectFailing;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.apache.servicecomb.saga.common.TransactionStatus;
+import org.apache.servicecomb.saga.omega.context.IdGenerator;
+import org.apache.servicecomb.saga.omega.context.OmegaContext;
+import org.apache.servicecomb.saga.omega.context.annotations.TccStart;
+import org.apache.servicecomb.saga.omega.transaction.AlphaResponse;
+import org.apache.servicecomb.saga.omega.transaction.tcc.events.ParticipatedEvent;
+import org.apache.servicecomb.saga.omega.transaction.tcc.events.TccEndedEvent;
+import org.apache.servicecomb.saga.omega.transaction.tcc.events.TccStartedEvent;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TccStartAspectTest {
+ private final ProceedingJoinPoint joinPoint = Mockito.mock(ProceedingJoinPoint.class);
+ private final MethodSignature methodSignature = Mockito.mock(MethodSignature.class);
+ private final String globalTxId = UUID.randomUUID().toString();
+ private final List<TccStartedEvent> startedEvents = new ArrayList<>();
+ private final List<TccEndedEvent> endedEvents = new ArrayList<>();
+ private final AlphaResponse response = new AlphaResponse(false);
+ private final TccEventService eventService = new TccEventService() {
+ @Override
+ public void onConnected() {
+
+ }
+
+ @Override
+ public void onDisconnected() {
+
+ }
+
+ @Override
+ public void close() {
+
+ }
+
+ @Override
+ public String target() {
+ return null;
+ }
+
+ @Override
+ public AlphaResponse participate(ParticipatedEvent participateEvent) {
+ return null;
+ }
+
+ @Override
+ public AlphaResponse TccTransactionStart(TccStartedEvent tccStartEvent) {
+ startedEvents.add(tccStartEvent);
+ return response;
+ }
+
+ @Override
+ public AlphaResponse TccTransactionStop(TccEndedEvent tccEndEvent) {
+ endedEvents.add(tccEndEvent);
+ return response;
+ }
+
+ };
+
+
+ @SuppressWarnings("unchecked")
+ private final IdGenerator<String> idGenerator = Mockito.mock(IdGenerator.class);
+ private final TccStart tccStart = Mockito.mock(TccStart.class);
+
+ private final OmegaContext omegaContext = new OmegaContext(idGenerator);
+ private final TccStartAspect aspect = new TccStartAspect(eventService, omegaContext);
+
+ @Before
+ public void setUp() throws Exception {
+ when(idGenerator.nextId()).thenReturn(globalTxId);
+ when(joinPoint.getSignature()).thenReturn(methodSignature);
+
+ when(methodSignature.getMethod()).thenReturn(this.getClass().getDeclaredMethod("doNothing"));
+ omegaContext.clear();
+ }
+
+ @Test
+ public void newGlobalTxIdInTccStart() throws Throwable {
+ aspect.advise(joinPoint, tccStart);
+
+ assertThat(startedEvents.size(), is(1));
+ TccStartedEvent startedEvent = startedEvents.get(0);
+
+ assertThat(startedEvent.getGlobalTxId(), is(globalTxId));
+ assertThat(startedEvent.getLocalTxId(), is(globalTxId));
+
+ assertThat(endedEvents.size(), is(1));
+ TccEndedEvent endedEvent = endedEvents.get(0);
+
+ assertThat(endedEvent.getGlobalTxId(), is(globalTxId));
+ assertThat(endedEvent.getLocalTxId(), is(globalTxId));
+ assertThat(endedEvent.getStatus(), is(TransactionStatus.Succeed));
+
+
+ assertThat(omegaContext.globalTxId(), is(nullValue()));
+ assertThat(omegaContext.localTxId(), is(nullValue()));
+ }
+
+ @Test
+ public void clearContextOnTccStartError() throws Throwable {
+ RuntimeException oops = new RuntimeException("oops");
+
+ when(joinPoint.proceed()).thenThrow(oops);
+
+ try {
+ aspect.advise(joinPoint, tccStart);
+ expectFailing(RuntimeException.class);
+ } catch (RuntimeException e) {
+ assertThat(e, is(oops));
+ }
+
+ assertThat(startedEvents.size(), is(1));
+ TccStartedEvent event = startedEvents.get(0);
+
+ assertThat(event.getGlobalTxId(), is(globalTxId));
+ assertThat(event.getLocalTxId(), is(globalTxId));
+
+ TccEndedEvent endedEvent = endedEvents.get(0);
+
+ assertThat(endedEvent.getGlobalTxId(), is(globalTxId));
+ assertThat(endedEvent.getLocalTxId(), is(globalTxId));
+ assertThat(endedEvent.getStatus(), is(TransactionStatus.Failed));
+
+ assertThat(omegaContext.globalTxId(), is(nullValue()));
+ assertThat(omegaContext.localTxId(), is(nullValue()));
+ }
+
+ private String doNothing() {
+ return "doNothing";
+ }
+
+
+}