/**
* Copyright (C) 2000-2016 Atomikos <info@atomikos.com>
*
* LICENSE CONDITIONS
*
* See http://www.atomikos.com/Main/WhichLicenseApplies for details.
*/
package com.atomikos.recovery.xa;
import static org.junit.Assert.assertNull;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.transaction.xa.Xid;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import com.atomikos.datasource.xa.XID;
import com.atomikos.recovery.LogReadException;
import com.atomikos.recovery.LogException;
import com.atomikos.recovery.ParticipantLogEntry;
import com.atomikos.recovery.RecoveryLog;
import com.atomikos.recovery.TxState;
public class DefaultXaRecoveryLogTestJUnit {
private static final String TID = "TID";
private static final String BRANCH = "BRANCH";
private DefaultXaRecoveryLog sut;
private RecoveryLog mock;
@Before
public void setUp() throws Exception {
mock = Mockito.mock(RecoveryLog.class);
sut = new DefaultXaRecoveryLog(mock);
}
@Test
public void testTerminated() {
XID xid = givenSomeXid();
whenTerminated(xid);
thenTerminatedInUnderlyingGenericLog(xid);
}
@Test
public void testPresumedAborting() throws IllegalStateException, LogException {
XID xid = givenSomeXid();
whenPresumedAborting(xid);
thenPresumedAbortingInUnderlyingGenericLog(xid);
}
@Test
public void testHeuristicRollbackByResource() throws IllegalStateException, LogException {
XID xid = givenSomeXid();
whenHeuristicRollback(xid);
thenHeuristicRollbackInUnderlyingGenericLog(xid);
}
@Test
public void testHeuristicCommitByResource() throws IllegalStateException, LogException {
XID xid = givenSomeXid();
whenHeuristicCommit(xid);
thenHeuristicCommitInUnderlyingGenericLog(xid);
}
@Test
public void testHeuristicHazardByResource() throws IllegalStateException, LogException {
XID xid = givenSomeXid();
whenHeuristicHazard(xid);
thenHeuristicHazardInUnderlyingGenericLog(xid);
}
@Test
public void testHeuristicMixedByResource() throws IllegalStateException, LogException {
XID xid = givenSomeXid();
whenHeuristicMixed(xid);
thenHeuristicMixedInUnderlyingGenericLog(xid);
}
@Test
public void testGetCommittingXids() throws LogReadException {
ParticipantLogEntry entry = givenCommittingParticipantLogEntryInGenericLog();
XID xid = whenGetExpiredCommittingXids();
thenGtidEqualsCoordinatorId(entry, xid);
thenParticipantEqualsXidBranchQualifierToString(entry, xid);
}
@Test
public void testTccParticipantLogEntryIsIgnored() throws LogReadException {
givenCommittingTccParticipantLogEntryInGenericLog();
Xid xid = whenGetExpiredCommittingXids();
assertNull(xid);
}
private void givenCommittingTccParticipantLogEntryInGenericLog() throws LogReadException {
ParticipantLogEntry entry = new ParticipantLogEntry("tid", "http://uri", 0, "desc", TxState.COMMITTING);
Collection<ParticipantLogEntry> c = new HashSet<ParticipantLogEntry>();
c.add(entry);
Mockito.when(mock.getCommittingParticipants()).thenReturn(c);
}
private void thenParticipantEqualsXidBranchQualifierToString(ParticipantLogEntry entry,
XID xid) {
Assert.assertEquals(entry.uri,xid.getBranchQualifierAsString());
}
private void thenGtidEqualsCoordinatorId(ParticipantLogEntry entry, XID xid) {
Assert.assertEquals(entry.coordinatorId, xid.getGlobalTransactionIdAsString());
}
private XID whenGetExpiredCommittingXids() throws LogReadException {
XID ret = null;
Set<XID> xids = sut.getExpiredCommittingXids();
if (!xids.isEmpty()) {
ret = xids.iterator().next();
}
return ret;
}
private ParticipantLogEntry givenCommittingParticipantLogEntryInGenericLog() throws LogReadException {
XID xid = givenSomeXid();
ParticipantLogEntry entry = new ParticipantLogEntry(xid.getGlobalTransactionIdAsString(), xid.toString(), 0, "desc", TxState.COMMITTING);
Collection<ParticipantLogEntry> c = new HashSet<ParticipantLogEntry>();
c.add(entry);
Mockito.when(mock.getCommittingParticipants()).thenReturn(c);
return entry;
}
private void thenHeuristicMixedInUnderlyingGenericLog(XID xid) throws LogException {
ParticipantLogEntry entry = convertXidToParticipantLogEntry(xid);
Mockito.verify(mock,Mockito.times(1)).terminatedWithHeuristicMixed(entry);
}
private void whenHeuristicMixed(XID xid) throws LogException {
sut.terminatedWithHeuristicMixedByResource(xid);
}
private void thenHeuristicHazardInUnderlyingGenericLog(XID xid) throws LogException {
ParticipantLogEntry entry = convertXidToParticipantLogEntry(xid);
Mockito.verify(mock,Mockito.times(1)).terminatedWithHeuristicHazard(entry);
}
private void whenHeuristicHazard(XID xid) throws LogException {
sut.terminatedWithHeuristicHazardByResource(xid);
}
private void thenHeuristicCommitInUnderlyingGenericLog(XID xid) throws LogException {
ParticipantLogEntry entry = convertXidToParticipantLogEntry(xid);
Mockito.verify(mock,Mockito.times(1)).terminatedWithHeuristicCommit(entry);
}
private void whenHeuristicCommit(XID xid) throws LogException {
sut.terminatedWithHeuristicCommitByResource(xid);
}
private void thenHeuristicRollbackInUnderlyingGenericLog(XID xid) throws LogException {
ParticipantLogEntry entry = convertXidToParticipantLogEntry(xid);
Mockito.verify(mock,Mockito.times(1)).terminatedWithHeuristicRollback(entry);
}
private void whenHeuristicRollback(XID xid) throws LogException {
sut.terminatedWithHeuristicRollbackByResource(xid);
}
private void thenPresumedAbortingInUnderlyingGenericLog(Xid xid) throws IllegalStateException, LogException {
ArgumentCaptor<ParticipantLogEntry> captor = ArgumentCaptor.forClass(ParticipantLogEntry.class);
Mockito.verify(mock,Mockito.times(1)).presumedAborting(captor.capture());
Assert.assertEquals(TxState.IN_DOUBT, captor.getValue().state);
}
private ParticipantLogEntry convertXidToParticipantLogEntry(XID xid) {
return new ParticipantLogEntry(xid.getGlobalTransactionIdAsString(), xid.getBranchQualifierAsString(), 0, "desc", TxState.COMMITTING);
}
private void whenPresumedAborting(XID xid) throws IllegalStateException, LogException {
sut.presumedAborting(xid);
}
private void thenTerminatedInUnderlyingGenericLog(XID xid) {
ParticipantLogEntry entry = convertXidToParticipantLogEntry(xid);
Mockito.verify(mock,Mockito.times(1)).terminated(entry);
}
private void whenTerminated(XID xid) {
sut.terminated(xid);
}
private XID givenSomeXid() {
return new XID(TID, BRANCH);
}
}