blob: 04c2a198d5f9d0039ea60d807cb88c90f9ddcf99 [file] [log] [blame]
/*
* 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.geode.internal.cache.backup;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.stubbing.Answer;
import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.persistence.PersistentID;
import org.apache.geode.distributed.internal.DistributionManager;
import org.apache.geode.distributed.internal.ReplyException;
import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
import org.apache.geode.internal.cache.InternalCache;
public class FinishBackupStepTest {
private DistributionManager dm;
private InternalCache cache;
private Set<InternalDistributedMember> recipients;
private InternalDistributedMember sender;
private InternalDistributedMember member1;
private InternalDistributedMember member2;
private boolean abort = false;
private FinishBackupFactory finishBackupFactory;
private BackupReplyProcessor finishBackupReplyProcessor;
private FinishBackupRequest finishBackupRequest;
private FinishBackup finishBackup;
private FinishBackupStep finishBackupStep;
@Before
public void setUp() throws Exception {
dm = mock(DistributionManager.class);
cache = mock(InternalCache.class);
finishBackupReplyProcessor = mock(BackupReplyProcessor.class);
finishBackupRequest = mock(FinishBackupRequest.class);
finishBackup = mock(FinishBackup.class);
finishBackupFactory = mock(FinishBackupFactory.class);
sender = mock(InternalDistributedMember.class, "sender");
member1 = mock(InternalDistributedMember.class, "member1");
member2 = mock(InternalDistributedMember.class, "member2");
recipients = new HashSet<>();
finishBackupStep =
new FinishBackupStep(dm, sender, cache, recipients, finishBackupFactory);
when(finishBackupReplyProcessor.getProcessorId()).thenReturn(42);
when(
finishBackupFactory.createReplyProcessor(eq(finishBackupStep), eq(dm), eq(recipients)))
.thenReturn(finishBackupReplyProcessor);
when(finishBackupFactory.createRequest(eq(sender), eq(recipients), eq(42)))
.thenReturn(finishBackupRequest);
when(finishBackupFactory.createFinishBackup(eq(cache))).thenReturn(finishBackup);
}
@Test
public void sendShouldSendfinishBackupMessage() throws Exception {
finishBackupStep.send();
verify(dm, times(1)).putOutgoing(finishBackupRequest);
}
@Test
public void sendReturnsResultsForRemoteRecipient() throws Exception {
HashSet<PersistentID> persistentIdsForMember1 = new HashSet<>();
persistentIdsForMember1.add(mock(PersistentID.class));
doAnswer(invokeAddToResults(new MemberWithPersistentIds(member1, persistentIdsForMember1)))
.when(finishBackupReplyProcessor).waitForReplies();
assertThat(finishBackupStep.send()).containsOnlyKeys(member1)
.containsValues(persistentIdsForMember1);
}
@Test
public void sendReturnsResultsForLocalMember() throws Exception {
HashSet<PersistentID> persistentIdsForSender = new HashSet<>();
persistentIdsForSender.add(mock(PersistentID.class));
when(finishBackup.run()).thenReturn(persistentIdsForSender);
assertThat(finishBackupStep.send()).containsOnlyKeys(sender)
.containsValue(persistentIdsForSender);
}
@Test
public void sendReturnsResultsForAllMembers() throws Exception {
HashSet<PersistentID> persistentIdsForMember1 = new HashSet<>();
persistentIdsForMember1.add(mock(PersistentID.class));
HashSet<PersistentID> persistentIdsForMember2 = new HashSet<>();
persistentIdsForMember2.add(mock(PersistentID.class));
MemberWithPersistentIds[] ids = new MemberWithPersistentIds[] {
new MemberWithPersistentIds(member1, persistentIdsForMember1),
new MemberWithPersistentIds(member2, persistentIdsForMember2)};
doAnswer(invokeAddToResults(ids)).when(finishBackupReplyProcessor).waitForReplies();
HashSet<PersistentID> persistentIdsForSender = new HashSet<>();
persistentIdsForSender.add(mock(PersistentID.class));
when(finishBackup.run()).thenReturn(persistentIdsForSender);
assertThat(finishBackupStep.send()).containsOnlyKeys(member1, member2, sender)
.containsValues(persistentIdsForSender, persistentIdsForMember1, persistentIdsForMember2);
}
@Test
public void getResultsShouldReturnEmptyMapByDefault() throws Exception {
assertThat(finishBackupStep.getResults()).isEmpty();
}
@Test
public void addToResultsWithNullShouldBeNoop() throws Exception {
finishBackupStep.addToResults(member1, null);
assertThat(finishBackupStep.getResults()).isEmpty();
}
@Test
public void addToResultsWithEmptySetShouldBeNoop() throws Exception {
finishBackupStep.addToResults(member1, new HashSet<>());
assertThat(finishBackupStep.getResults()).isEmpty();
}
@Test
public void addToResultsShouldShowUpInGetResults() throws Exception {
HashSet<PersistentID> persistentIdsForMember1 = new HashSet<>();
persistentIdsForMember1.add(mock(PersistentID.class));
finishBackupStep.addToResults(member1, persistentIdsForMember1);
assertThat(finishBackupStep.getResults()).containsOnlyKeys(member1)
.containsValue(persistentIdsForMember1);
}
@Test
public void sendShouldHandleIOExceptionThrownFromRun() throws Exception {
when(finishBackup.run()).thenThrow(new IOException("expected exception"));
finishBackupStep.send();
}
@Test(expected = RuntimeException.class)
public void sendShouldThrowNonIOExceptionThrownFromRun() throws Exception {
when(finishBackup.run()).thenThrow(new RuntimeException("expected exception"));
finishBackupStep.send();
}
@Test
public void sendShouldHandleCancelExceptionFromWaitForReplies() throws Exception {
ReplyException replyException =
new ReplyException("expected exception", new CacheClosedException("expected exception"));
doThrow(replyException).when(finishBackupReplyProcessor).waitForReplies();
finishBackupStep.send();
}
@Test
public void sendShouldHandleInterruptedExceptionFromWaitForReplies() throws Exception {
doThrow(new InterruptedException("expected exception")).when(finishBackupReplyProcessor)
.waitForReplies();
finishBackupStep.send();
}
@Test(expected = ReplyException.class)
public void sendShouldThrowReplyExceptionWithNoCauseFromWaitForReplies() throws Exception {
doThrow(new ReplyException("expected exception")).when(finishBackupReplyProcessor)
.waitForReplies();
finishBackupStep.send();
}
@Test(expected = ReplyException.class)
public void sendShouldThrowReplyExceptionWithCauseThatIsNotACancelFromWaitForReplies()
throws Exception {
doThrow(new ReplyException("expected exception", new RuntimeException("expected")))
.when(finishBackupReplyProcessor).waitForReplies();
finishBackupStep.send();
}
@Test
public void sendShouldfinishForBackupInLocalMemberBeforeWaitingForReplies() throws Exception {
InOrder inOrder = inOrder(finishBackup, finishBackupReplyProcessor);
finishBackupStep.send();
inOrder.verify(finishBackup, times(1)).run();
inOrder.verify(finishBackupReplyProcessor, times(1)).waitForReplies();
}
private Answer<Object> invokeAddToResults(MemberWithPersistentIds... memberWithPersistentIds) {
return invocation -> {
for (MemberWithPersistentIds ids : memberWithPersistentIds) {
finishBackupStep.addToResults(ids.member, ids.persistentIds);
}
return null;
};
}
private static class MemberWithPersistentIds {
InternalDistributedMember member;
HashSet<PersistentID> persistentIds;
MemberWithPersistentIds(InternalDistributedMember member, HashSet<PersistentID> persistentIds) {
this.member = member;
this.persistentIds = persistentIds;
}
}
}