package com.workshare.msnos.core.receipts;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import com.workshare.msnos.core.LocalAgent;
import com.workshare.msnos.core.Message;
import com.workshare.msnos.core.Message.Status;
import com.workshare.msnos.core.MessageBuilder;
import com.workshare.msnos.core.Receipt;
public class MultiReceiptTest {
private static final Message MESSAGE = new MessageBuilder(Message.Type.PIN, new LocalAgent(UUID.randomUUID()), new LocalAgent(UUID.randomUUID())).make();
private MultiReceipt multi;
private Receipt[] receipts = new Receipt[3];
@Before
public void before() throws Exception {
multi = new MultiReceipt(MESSAGE);
for (int i = 0; i < receipts.length; i++) {
receipts[i] = createMockReceipt(Status.UNKNOWN, i);
multi.add(receipts[i]);
}
}
@Test
public void shouldReturnUnknownWhenBothUnknown() throws Exception {
assertEquals(Status.UNKNOWN, multi.getStatus());
}
@Test
public void shouldReturnFailedWhenOneFailedAndOtherUnknown() throws Exception {
mockStatus(receipts[1], Status.FAILED);
assertEquals(Status.FAILED, multi.getStatus());
}
@Test
public void shouldReturnPendingWhenOnePending() throws Exception {
mockStatus(receipts[0], Status.PENDING);
mockStatus(receipts[1], Status.FAILED);
mockStatus(receipts[2], Status.FAILED);
assertEquals(Status.PENDING, multi.getStatus());
}
@Test
public void shouldReturnDeliverdWhenOneDelivered() throws Exception {
mockStatus(receipts[1], Status.PENDING);
mockStatus(receipts[2], Status.DELIVERED);
assertEquals(Status.DELIVERED, multi.getStatus());
}
@Test
public void shouldWaitForTimeoutsOnAllReceipts() throws InterruptedException {
multi.waitForDelivery(100 * receipts.length, TimeUnit.MILLISECONDS);
for (Receipt receipt : receipts) {
verify(receipt, atLeastOnce()).waitForDelivery(anyLong(), eq(TimeUnit.MILLISECONDS));
}
}
@Test
public void shouldReturnFalseWhenNoneDeliveredOnWaitFor() throws InterruptedException {
boolean res = multi.waitForDelivery(100, TimeUnit.MILLISECONDS);
assertFalse(res);
}
@Test
public void shouldReturnTrueWhenOnWaitforSucceeds() throws InterruptedException {
when(receipts[1].waitForDelivery(anyLong(), any(TimeUnit.class))).thenReturn(true);
boolean res = multi.waitForDelivery(100, TimeUnit.MILLISECONDS);
assertTrue(res);
}
@Test
public void shouldReturnTrueWhenOnWaitforFailsButOneIsDelivered() throws InterruptedException {
mockStatus(receipts[2], Status.DELIVERED);
boolean res = multi.waitForDelivery(100, TimeUnit.MILLISECONDS);
assertTrue(res);
}
@Test
public void shouldWaitForTimeoutsWhenNoReceipts() throws InterruptedException {
long now = System.currentTimeMillis();
multi = new MultiReceipt(MESSAGE);
multi.waitForDelivery(100, TimeUnit.MILLISECONDS);
assertTrue(System.currentTimeMillis() > now + 100);
}
@Test
public void shouldStoreMessageUuid() throws Exception {
assertEquals(MESSAGE.getUuid(), multi.getMessageUuid());
}
@Test
public void shouldReturnCombinedNameWhenAllUnknown() throws Exception {
String gate = multi.getGate();
for (Receipt receipt : receipts) {
assertTrue(gate.contains(receipt.getGate()));
}
}
@Test
public void shouldReturnNameForTheFirstDelivered() throws InterruptedException {
mockStatus(receipts[1], Status.DELIVERED);
assertEquals(receipts[1].getGate(), multi.getGate());
}
private Receipt createMockReceipt(final Status status, int number) throws Exception {
Receipt value = mock(Receipt.class);
mockStatus(value, status);
when(value.getGate()).thenReturn(Integer.toString(number));
return value;
}
private void mockStatus(Receipt receipt, final Status status) {
when(receipt.getStatus()).thenReturn(status);
}
}